/decss

Present from the Web, Beautifully

Primary LanguageJavaScript

Decss

Present from the Web, Beautifully

Decss was designed from the ground up to be a presenter-friendly way to give presentations in HTML/CSS/JS. Using modern markup, with the old <center> tag repurposed, you can quickly build a deck that everyone will love.

Requirements

To stay lightweight, Decss requires modern browser functionality. However, if you want to support older browsers, you may use https://github.com/inexorabletash/polyfill and https://github.com/douglascrockford/JSON-js to meet the requirements.

When a browser does not meet all the requirements, a class of not-supported is added to <html> tag. You may use that class to show a message to viewers.

Basic Usage

Three files are required to use Decss: modernizr.js, decss.min.js and decss.css. You can host these yourself or get point to:

If you want to use your own version of Modernizr, please include the Flexible Box Model (not the legacy version), CSS 3D Transforms and CSS Boxsizing (available under non-core detects) tests.

<!doctype HTML>
<html class="no-js">
    <head>
        <title>My Awesome Presentation</title>
        <link href="http://dryan.github.io/decss/css/decss.css" rel="stylesheet">
        <script src="http://dryan.github.io/decss/js/modernizr.js"></script>
    </head>
    <body>
        <script src="http://dryan.github.io/decss/js/decss.min.js"></script>
    </body>
</html>

Markup

A deck consists of a container element with id="deck" (the "deck element") containing one or more <section>s, which act as the slides.

<body>
    <main id="deck">
        <section id="intro">
            <header>
                <h1>Welcome to My Awesome Presentation</h1>
            </header>
            <center>
                <p>Here's some bullets:</p>
                <ul>
                    <li>To being with</li>
                    <li>But also</li>
                    <li>And finally</li>
                </ul>
            </center>
        </section>
    </main>
</body>

Each slide may contain any markup you choose. The <header> and <center> tags act as special layout triggers. In browsers that support the modern flexbox syntax, content inside the <center> tag will be vertically centered in a single column. <center class="horizontal"> will align its children in a single row, instead. A <header> that is the only child of a <section> acts like a <center> tag as well.

Images

To place multiple images in a row, wrap them with a <figure> tag. Additionally, add a class of two-up, three-up, four-up or five-up depending on how many images there are.

<figure class="three-up">
    <img src="http://placekitten.com/a/200/300" width="200" height="300" alt="Aww a kitty!">
    <img src="http://placekitten.com/b/200/300" width="200" height="300" alt="Aww another kitty!">
    <img src="http://placekitten.com/c/200/300" width="200" height="300" alt="More kittens!">
</figure>

Background Images

Slide backgrounds are set using the normal CSS background-image property. Decss sets these to use background-size: cover for you.

<!-- inline background -->
<section id="intro" style="background-image: url('http://placekitten.com/1280/1280')">
</section>

<!-- CSS style tag or external file -->
<section id="intro">
</section>
<style>
    #intro {
        background-image: url('http://placekitten.com/1280/1280');
    }
</style>

Builds / Steps

Sometimes you want items to appear manually instead of when the slide first appears. Adding a data-step attribute to elements achieves this.

<section id="my-slide">
    <header>
        <h1>Building Suspense</h1>
    </header>
    <center>
        <ul>
            <li data-step="1">Step 1</li>
            <li data-step="2">Step 2</li>
            <li data-step="3">Step 3</li>
        </ul>
    </center>
</section>

In this example, no bullets would be visible at first. As you navigate forward through the deck, each one will show in turn. Once the last step has become visible, navigating forward again moves on to the next slide. Note that multiple elements can share the same step and will be made visible at the same time.

Steps may also be nested:

<section id="my-slide">
    <header>
        <h1>Building Suspense</h1>
    </header>
    <center>
        <ul>
            <li data-step="1">Step 1<span data-step="2">: but wait, there's more!</span></li>
            <li data-step="3">Step 2</li>
            <li data-step="4">Step 3</li>
        </ul>
    </center>
</section>

In this example, the first bullet would appear with just "Step 1" visible, then the rest would appear before "Step 2".

Audio and Video

Decss supports multimedia via <audio> and <video> tags. Elements that have a data-step attribute will be played when their step number is reached. Elements without a data-step attribute and without a controls attribute are played automatically when their slide is shown.

<section id="media-slide">
    <header>
        <h1>Check out this awesome video</h1>
    </header>
    <center>
        <video src="http://pdl.vimeocdn.com/70085/179/156173617.mp4" width="1280" height="720" data-step="1" controls>
        <audio src="/audio/sadtrombone.mp3">
    </center>    
</section>

In this example, the video will play when the deck is navigated forward after this slide appears. The audio file will play when the slide first appears.

Navigation

The following keys may be used to navigate through the deck:

  • Beginning of deck: home
  • End of deck: end
  • Previous slide/step: left arrow, page up, J or j
  • Next slide/step: right arrow, page down, K or k
  • Presenter mode: control+escape, P or p (note that control+escape is a system shortcut on Windows)
  • Fullscreen mode: F or f

Additionally, on touch enabled devices, swiping towards the right edge of the screen goes forwards and swiping towards the left edge goes backwards.

Swiping gestures require a minimum movement of 150 pixels, though a larger threshold can be set by adding a data-touch-distance attribute to the deck element. Additionally, swipes must start and end in 500 milliseconds or less; adding a data-touch-duration larger than 500 will override this setting.

Transition Styles

Currently Decss has two transition styles available: fade and zoom. The transition style is set via the <body> tag's data-transition attribute. <body data-transition="zoom">, for example. If no transition is specified, fade is used.

A third style, slide, is in the works but is pretty buggy at the moment.

Presenter Mode

Pressing control+escape will toggle a presenter mode. In this mode, you will see the current slide with any unrevealed steps slightly visible, the next slide to be shown, a timer of how long the presentation has been running and a selector to jump between slides. Beneath each slide is the number of the current slide, which step that slide is on, and any presenter notes set with a data-notes attribute on the slide.

Presentation mode adds a presenter class to the <html> tag that you can use for addition styling.

Customizing the Deck's Style

You can include the base decss.css file and then override it with your own CSS, but the better method is to use SASS to create your own custom CSS file.

// set the initial variables
$bodyBackground:            black;
$bodyColor:                 white;
$bodyFont:                  'Open Sans', sans-serif;
$bodyWeight:                400;
$bodyFontSizeBase:          16px;
$bodyFontSizeLarge:         24px;

@import "decss";

// add more custom styles below

See the variables.scss file for the complete list of options. Customizing the SASS files requires bourbon.io.

Multi-screen Syncing

To syncronize presentations across multiple devices, you will need to create a Deck ID at sync.dryan.io or run an instance of decss-sync. On the deck element, set the data-sync-server attribute to point to the correct sync server.

By default, the WebSocket connection is made over SSL. If you're running your own instance of decss-sync without SSL support, add data-sync-insecure="true" to your deck element. sync.dryan.io will not work over insecure connections.

When syncing is first setup, the deck element gets a data-in-control="true" or data-in-control="false" attribute added, depending on if the viewer is logged into the sync server and owns this deck.

JavaScript API

Once the deck is setup, the window.Decss variable will point to the current Deck object. This object has several properties and methods you may use. Properties and methods beginning with __ are considered private and are subject to change in the future.

Slide Instances

Each slide is represented as an HTMLNode with the following properties added:

  • steps: the highest numbered step in this slide
  • currentStep: the current step being displayed

Decss.changeToSlide(slide, step, sender)

Use this method to change to a specific slide and step.

The slide argument may be an instance of a slide, the id attribute of a slide (with or without the # at the beginning) or the number of the slide in the deck (zero-based);

If step is set, the given slide will be set to that step. Leaving it null will keep the slide in its current state.

The sender argument is used to track the source of the changeToSlide call. This is passed on to emitted events for use by event listeners.

Decss.allowControl

A boolean indicating if this viewer has allowed the sync server to control navigation.

Decss.currentPosition

The index of the current slide in the Decss.slides array.

Decss.currentSlide

The slide instance of the currently visible slide.

Decss.debug

A boolean indicating if this deck is in debug mode or not. Initially set from the deck element's data-debug attribute. In debug mode, additional information will be sent to the JavaScript console.

Decss.deck

The HTMLNode for the deck element.

Decss.end()

Navigates to the final slide of the deck.

Decss.fullscreen

A boolean indicating if the deck is currently fullscreen or not.

Decss.goFullscreen()

Requests that the browser display the deck in fullscreen mode.

Decss.home()

Navigates to the first slide of the deck and resets its currentStep to 0.

Decsss.id

The value of the deck element's data-id attribute. Used by multi-screen syncing.

Decss.inControl

A boolean indicating if this Deck instance is controlling remote viewers.

Decss.init()

Does all of the setup work to present the deck. This is called automatically by the script, but if you programattically change the contents of the deck, you should run this again.

Decss.next()

Navigates one step or slide ahead.

Decss.previous()

Navigates one step or slide behind.

Decss.slides

An array of all the slide instances in the deck.

Decss.touchDistance

An integer of how many pixels a swipe gesture must be to be considered for navigation. Determined intially by the deck element's data-touch-distance attribute.

Decss.touchDuration

An integer of how many milliseconds a swipe gesture must occur within to be considered for navigation. Determined initially by the deck element's data-touch-duration attribute.

JavaScript Events

There are several events that you may attach listeners to in order to interact with the deck programattically. Each event is sent from the deck element, so you must attach either to that element or one of its parents to receive the events. See the sample Google Analyics integration for a demo.

Each event's detail property is an object. Every event detail has a deck property pointing to the Deck instance that sent the event. Some events' details also have a sender property is added to the event's detail indicating if the end event was reached via keyboard, touch, message (from the sync server) or a custom sender that you have used. Additionally, some events have additional properties as outlined below.

decssinit

Emitted when Decss.init() has completed. Does not indicate a sender.

decssend

Emitted when the final slide is visible and its final step has been shown.

decsschange

Emitted everytime changeToSlide is called. In addition to deck and sender, a decsschange event's detail contains the following properties:

  • slide: the slide that was changed to
  • step: the step that was changed to

Examples:

// Example 1
document.addEventListener('decsschange', function(e) {
    if(e.detail.slide.id === 'intro' && e.detail.slide.currentStep === 0) {
        Decss.next();
    }
}, false);
// Example 2
document.addEventListener('decssend', function(e) {
    window.alert('You have reached the end of our journey');
}, false);

In Example 1, whenever the slide with the id 'intro' is shown, if that slide is at the initial step, automatically show the next step.

In Example 2, when the deck is finished, an alert will be triggered.