more work on presentation

parent 3f523a8e
So you like the style of impress.js demo?
Or maybe you are just curious how it was done?
You couldn't find a better place to find out!
Welcome to the stylesheet impress.js demo presentation.
Please remember that it is not meant to be a part of impress.js and is
not required by impress.js.
I expect that anyone creating a presentation for impress.js would create
their own set of styles.
But feel free to read through it and learn how to get the most of what
impress.js provides.
And let me be your guide.
Shall we begin?
We start with a good ol' reset.
That's the one by Eric Meyer
......@@ -86,11 +64,6 @@ body {
min-height: 740px;
background: rgb(215, 215, 215);
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190)));
background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -ms-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
......@@ -111,10 +84,6 @@ a {
text-shadow: -1px -1px 2px rgba(100,100,100,0.9);
border-radius: 0.2em;
-webkit-transition: 0.5s;
-moz-transition: 0.5s;
-ms-transition: 0.5s;
-o-transition: 0.5s;
transition: 0.5s;
......@@ -124,38 +93,6 @@ a:focus {
text-shadow: -1px -1px 2px rgba(100,100,100,0.5);
Because the main point behind the impress.js demo is to demo impress.js
we display a fallback message for users with browsers that don't support
all the features required by it.
All of the content will be still fully accessible for them, but I want
them to know that they are missing something - that's what the demo is
about, isn't it?
And then we hide the message, when support is detected in the browser.
.fallback-message {
font-family: sans-serif;
line-height: 1.3;
width: 780px;
padding: 10px 10px 0;
margin: 20px auto;
border: 1px solid #E4C652;
border-radius: 10px;
background: #EEDC94;
.fallback-message p {
margin-bottom: 10px;
.impress-supported .fallback-message {
display: none;
Now let's style the presentation steps.
......@@ -169,10 +106,6 @@ a:focus {
padding: 40px;
margin: 20px auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
font-family: 'PT Serif', georgia, serif;
......@@ -253,6 +186,10 @@ a:focus {
.intro {
.intro h1 {
font-size: 76px;
font-weight: bold;
......@@ -262,24 +199,61 @@ a:focus {
And now we start to style each step separately.
I agree that this may be not the most efficient, object-oriented and
scalable way of styling, but most of steps have quite a custom look
and typography tricks here and there, so they had to be styled separately.
First is the title step with a big <h1> (no room for padding) and some
3D positioning along Z axis.
The title
@keyframes rotate-h1 {
0% { transform: perspective(1000px) rotateY(-5deg); }
100% { transform: perspective(1000px) rotateY(5deg); }
#title h1 {
font-weight: bold;
text-align: center;
font-size: 5em;
line-height: 0.5;
transform-style: preserve-3d;
animation: rotate-h1 5s infinite alternate ease-in-out;
transform: perspective(1000px) rotateY(0deg);
transition: all 2s ease-in-out;
#title h1 .grains {
transform: translateZ(100px);
#title h1 .sounds {
text-transform: lowercase;
display: inline-block;
font-weight: normal;
font-size: 0.3em;
transform: translateZ(50px);
#title h1 .d3 {
display: inline-block;
transform: translateZ(20px);
#title h1 .universe {
display: inline-block;
font-weight: normal;
font-size: 0.3em;
transform: translateY(-0.5em) translateZ(-50px);
transform: translateZ(50px);
#title ul {
text-align: center;
Second step is nothing special, just a text with a link, so it doesn't need
any special styling.
......@@ -502,178 +476,3 @@ a:focus {
opacity: 1;
cursor: pointer;
Now, when we have all the steps styled let's give users a hint how to navigate
around the presentation.
The best way to do this would be to use JavaScript, show a delayed hint for a
first time users, then hide it and store a status in cookie or localStorage...
But I wanted to have some CSS fun and avoid additional scripting...
Let me explain it first, so maybe the transition magic will be more readable
when you read the code.
First of all I wanted the hint to appear only when user is idle for a while.
You can't detect the 'idle' state in CSS, but I delayed a appearing of the
hint by 5s using transition-delay.
You also can't detect in CSS if the user is a first-time visitor, so I had to
make an assumption that I'll only show the hint on the first step. And when
the step is changed hide the hint, because I can assume that user already
knows how to navigate.
To summarize it - hint is shown when the user is on the first step for longer
than 5 seconds.
The other problem I had was caused by the fact that I wanted the hint to fade
in and out. It can be easily achieved by transitioning the opacity property.
But that also meant that the hint was always on the screen, even if totally
transparent. It covered part of the screen and you couldn't correctly clicked
through it.
Unfortunately you cannot transition between display `block` and `none` in pure
CSS, so I needed a way to not only fade out the hint but also move it out of
the screen.
I solved this problem by positioning the hint below the bottom of the screen
with CSS transform and moving it up to show it. But I also didn't want this move
to be visible. I wanted the hint only to fade in and out visually, so I delayed
the fade in transition, so it starts when the hint is already in its correct
position on the screen.
I know, it sounds complicated ... maybe it would be easier with the code?
.hint {
We hide the hint until presentation is started and from browsers not supporting
impress.js, as they will have a linear scrollable view ...
display: none;
... and give it some fixed position and nice styles.
position: fixed;
left: 0;
right: 0;
bottom: 200px;
background: rgba(0,0,0,0.5);
color: #EEE;
text-align: center;
font-size: 50px;
padding: 20px;
z-index: 100;
By default we don't want the hint to be visible, so we make it transparent ...
opacity: 0;
... and position it below the bottom of the screen (relative to it's fixed position)
-webkit-transform: translateY(400px);
-moz-transform: translateY(400px);
-ms-transform: translateY(400px);
-o-transform: translateY(400px);
transform: translateY(400px);
Now let's imagine that the hint is visible and we want to fade it out and move out
of the screen.
So we define the transition on the opacity property with 1s duration and another
transition on transform property delayed by 1s so it will happen after the fade out
on opacity finished.
This way user will not see the hint moving down.
-webkit-transition: opacity 1s, -webkit-transform 0.5s 1s;
-moz-transition: opacity 1s, -moz-transform 0.5s 1s;
-ms-transition: opacity 1s, -ms-transform 0.5s 1s;
-o-transition: opacity 1s, -o-transform 0.5s 1s;
transition: opacity 1s, transform 0.5s 1s;
Now we 'enable' the hint when presentation is initialized ...
.impress-enabled .hint { display: block }
... and we will show it when the first step (with id 'bored') is active.
.impress-on-title .hint {
We remove the transparency and position the hint in its default fixed
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
Now for fade in transition we have the oposite situation from the one
First after 4.5s delay we animate the transform property to move the hint
into its correct position and after that we fade it in with opacity
-webkit-transition: opacity 1s 5s, -webkit-transform 0.5s 4.5s;
-moz-transition: opacity 1s 5s, -moz-transform 0.5s 4.5s;
-ms-transition: opacity 1s 5s, -ms-transform 0.5s 4.5s;
-o-transition: opacity 1s 5s, -o-transform 0.5s 4.5s;
transition: opacity 1s 5s, transform 0.5s 4.5s;
And as the last thing there is a workaround for quite strange bug.
It happens a lot in Chrome. I don't remember if I've seen it in Firefox.
Sometimes the element positioned in 3D (especially when it's moved back
along Z axis) is not clickable, because it falls 'behind' the <body>
To prevent this, I decided to make <body> non clickable by setting
pointer-events property to `none` value.
Value if this property is inherited, so to make everything else clickable
I bring it back on the #impress element.
If you want to know more about `pointer-events` here are some docs:
There is one very important thing to notice about this workaround - it makes
everything 'unclickable' except what's in #impress element.
So use it wisely ... or don't use at all.
.impress-enabled { pointer-events: none }
.impress-enabled #impress { pointer-events: auto }
There is one funny thing I just realized.
Thanks to this workaround above everything except #impress element is invisible
for click events. That means that the hint element is also not clickable.
So basically all of this transforms and delayed transitions trickery was probably
not needed at all...
But it was fun to learn about it, wasn't it?
That's all I have for you in this file.
Thanks for reading. I hope you enjoyed it at least as much as I enjoyed writing it
for you.
......@@ -20,37 +20,15 @@
<body class="impress-not-supported">
<div class="fallback-message">
<p>Your browser <b>doesn't support the features required</b> by impress.js, so you are presented with a simplified version of this presentation.</p>
<p>For the best experience please use the latest <b>Chrome</b>, <b>Safari</b> or <b>Firefox</b> browser.</p>
Now that's the core element used by impress.js.
That's the wrapper for your presentation steps. In this element all the impress.js magic happens.
It doesn't have to be a `<div>`. Only `id` is important here as that's how the script find it.
You probably won't need it now, but there are some configuration options that can be set on this element.
To change the duration of the transition between slides use `data-transition-duration="2000"` giving it
a number of ms. It defaults to 1000 (1s).
You can also control the perspective with `data-perspective="500"` giving it a number of pixels.
It defaults to 1000. You can set it to 0 if you don't want any 3D effects.
If you are willing to change this value make sure you understand how CSS perspective works:
But as I said, you won't need it for now, so don't worry - there are some simple but interesting things
right around the corner of this tag ;)
<div id="impress">
<div id="title" class="step slide" data-x="-1000" data-y="-1500">
<h2>We are sounds in the Universe</h2>
<div id="title" class="step" data-x="-1000" data-y="-1500">
<span class="grains">Grains</span>
<span class="sounds">We are sounds</span>
<span class="universe">in the universe</span>
<li>Dragica Kahlina (@gluggergames)</li>
<li>Jens-Christian Fischer (@jcfischer)</li>
......@@ -89,92 +67,51 @@
<div class="step slide" data-x="1000" data-y="-1500">
<q>Would you like to <strong>impress your audience</strong> with <strong>stunning visualization</strong> of your talk?</q>
<h1>Sound Synthesis</h1>
<div class="step slide" data-x="1000" data-y="-1500" data-z="-1000">
<h1>Subtractive Synthesis</h1>
<q>Start with a sound with lots of harmonic contents, then shape and filter it<q>
<div class="step slide" data-x="1000" data-y="-1500" data-z="-2000">
This is an example of step element being scaled.
<h1>Additive Synthesis</h1>
<q>Start with a sine wave and add more (harmonic) sine waves on top of it</q>
Again, we use a `data-` attribute, this time it's `data-scale="4"`, so it means that this
element will be 4 times larger than the others.
From presentation and transitions point of view it means, that it will have to be scaled
down (4 times) to make it back to its correct size.
<div id="xtitle" class="step" data-x="0" data-y="0" data-scale="4">
<span class="try">then you should try</span>
<span class="footnote"><sup>*</sup> no rhyme intended</span>
<h1>Granular synthesis</h1>
This element introduces rotation.
Notation shouldn't be a surprise. We use `data-rotate="90"` attribute, meaning that this
element should be rotated by 90 degrees clockwise.
<div id="its" class="step" data-x="850" data-y="3000" data-rotate="90" data-scale="5">
<p>It’s a <strong>presentation tool</strong> <br/>
inspired by the idea behind <a href=""></a> <br/>
and based on the <strong>power of CSS3 transforms and transitions</strong> in modern browsers.</p>
<h1>Audience Participation</h1>
<p>Let's experiment with <b>granular synthesis</b></p>
<p>Each one of you will be <b>control</b> one <i>grain</i> and be part of the sound</p>
<div id="big" class="step" data-x="3500" data-y="2100" data-rotate="180" data-scale="6">
<p>visualize your <b>big</b> <span class="thoughts">thoughts</span></p>
<li>Elixir / Erlang / Phoenix</li>
<li>Open Sound Control (OSC)</li>
And now it gets really exciting! We move into third dimension!
Along with `data-x` and `data-y`, you can define the position on third (Z) axis, with
`data-z`. In the example below we use `data-z="-3000"` meaning that element should be
positioned far away from us (by 3000px).
<div id="tiny" class="step" data-x="2825" data-y="2325" data-z="-3000" data-rotate="300" data-scale="1">
<p>and <b>tiny</b> ideas</p>
This step here doesn't introduce anything new when it comes to data attributes, but you
should notice in the demo that some words of this text are being animated.
It's a very basic CSS transition that is applied to the elements when this step element is
At the very beginning of the presentation all step elements are given the class of `future`.
It means that they haven't been visited yet.
When the presentation moves to given step `future` is changed to `present` class name.
That's how animation on this step works - text moves when the step has `present` class.
Finally when the step is left the `present` class is removed from the element and `past`
class is added.
So basically every step element has one of three classes: `future`, `present` and `past`.
Only one current step has the `present` class.
<div id="ing" class="step" data-x="3500" data-y="-850" data-rotate="270" data-scale="6">
<p>by <b class="positioning">positioning</b>, <b class="rotating">rotating</b> and <b class="scaling">scaling</b> them on an infinite canvas</p>
<q>Go to</q>
<p><a href=""></a>
<div id="imagination" class="step" data-x="6700" data-y="-300" data-scale="6">
<p>the only <b>limit</b> is your <b class="imagination">imagination</b></p>
<div id="source" class="step" data-x="6300" data-y="2000" data-rotate="20" data-scale="4">
<p>want to know more?</p>
<q><a href="">use the source</a>, Luke!</q>
<div id="one-more-thing" class="step" data-x="6000" data-y="4000" data-scale="2">
<p>one more thing...</p>
......@@ -213,38 +150,6 @@
Hint is not related to impress.js in any way.
But it can show you how to use impress.js features in creative way.
When the presentation step is shown (selected) its element gets the class of "active" and the body element
gets the class based on active step id `impress-on-ID` (where ID is the step's id)... It may not be
so clear because of all these "ids" in previous sentence, so for example when the first step (the one with
the id of `bored`) is active, body element gets a class of `impress-on-bored`.
This class is used by this hint below. Check CSS file to see how it's shown with delayed CSS animation when
the first step of presentation is visible for a couple of seconds.
And when it comes to this piece of JavaScript below ... kids, don't do this at home ;)
It's just a quick and dirty workaround to get different hint text for touch devices.
In a real world it should be at least placed in separate JS file ... and the touch content should be
probably just hidden somewhere in HTML - not hard-coded in the script.
Just sayin' ;)
<div class="hint">
<p>Use a spacebar or arrow keys to navigate</p>
if ("ontouchstart" in document.documentElement) {
document.querySelector(".hint").innerHTML = "<p>Tap on the left or right to navigate</p>";
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment