1/* 2 So you like the style of impress.js demo? 3 Or maybe you are just curious how it was done? 4 5 You couldn't find a better place to find out! 6 7 Welcome to the stylesheet impress.js demo presentation. 8 9 Please remember that it is not meant to be a part of impress.js and is 10 not required by impress.js. 11 I expect that anyone creating a presentation for impress.js would create 12 their own set of styles. 13 14 But feel free to read through it and learn how to get the most of what 15 impress.js provides. 16 17 And let me be your guide. 18 19 Shall we begin? 20*/ 21 22 23/* 24 We start with a good ol' reset. 25 That's the one by Eric Meyer http://meyerweb.com/eric/tools/css/reset/ 26 27 You can probably argue if it is needed here, or not, but for sure it 28 doesn't do any harm and gives us a fresh start. 29*/ 30 31html, body, div, span, applet, object, iframe, 32p, blockquote, pre, 33a, abbr, acronym, address, big, cite, code, 34del, dfn, em, img, ins, kbd, q, s, samp, 35small, strike, strong, sub, sup, tt, var, 36b, u, i, center, 37dl, dt, dd, ol, ul, li, 38fieldset, form, label, legend, 39table, caption, tbody, tfoot, thead, tr, th, td, 40article, aside, canvas, details, embed, 41figure, figcaption, footer, header, hgroup, 42menu, nav, output, ruby, section, summary, 43time, mark, audio, video { 44 margin: 0; 45 padding: 0; 46 border: 0; 47 font-size: 100%; 48 font: inherit; 49 vertical-align: baseline; 50} 51 52/* HTML5 display-role reset for older browsers */ 53article, aside, details, figcaption, figure, 54footer, header, hgroup, menu, nav, section { 55 display: block; 56} 57body { 58 line-height: 1; 59} 60ol, ul { 61 list-style: none; 62} 63blockquote, q { 64 quotes: none; 65} 66blockquote:before, blockquote:after, 67q:before, q:after { 68 content: ''; 69 content: none; 70} 71 72table { 73 border-collapse: collapse; 74 border-spacing: 0; 75} 76 77/* 78 Now here is when interesting things start to appear. 79 80 We set up <body> styles with default font and nice gradient in the background. 81 And yes, there is a lot of repetition there because of -prefixes but we don't 82 want to leave anybody behind. 83*/ 84body { 85 font-family: 'PT Sans', sans-serif; 86 min-height: 740px; 87 88 background: rgb(215, 215, 215); 89 background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190))); 90 background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 91 background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 92 background: -ms-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 93 background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 94 background: radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 95} 96 97/* 98 Now let's bring some text styles back ... 99*/ 100b, strong { font-weight: bold } 101i, em { font-style: italic } 102 103/* 104 ... and give links a nice look. 105*/ 106a { 107 color: inherit; 108 text-decoration: none; 109 padding: 0 0.1em; 110 background: rgba(255,255,255,0.5); 111 text-shadow: -1px -1px 2px rgba(100,100,100,0.9); 112 border-radius: 0.2em; 113 114 -webkit-transition: 0.5s; 115 -moz-transition: 0.5s; 116 -ms-transition: 0.5s; 117 -o-transition: 0.5s; 118 transition: 0.5s; 119} 120 121a:hover, 122a:focus { 123 background: rgba(255,255,255,1); 124 text-shadow: -1px -1px 2px rgba(100,100,100,0.5); 125} 126 127/* 128 Because the main point behind the impress.js demo is to demo impress.js 129 we display a fallback message for users with browsers that don't support 130 all the features required by it. 131 132 All of the content will be still fully accessible for them, but I want 133 them to know that they are missing something - that's what the demo is 134 about, isn't it? 135 136 And then we hide the message, when support is detected in the browser. 137*/ 138 139.fallback-message { 140 font-family: sans-serif; 141 line-height: 1.3; 142 143 width: 780px; 144 padding: 10px 10px 0; 145 margin: 20px auto; 146 147 border: 1px solid #E4C652; 148 border-radius: 10px; 149 background: #EEDC94; 150} 151 152.fallback-message p { 153 margin-bottom: 10px; 154} 155 156.impress-supported .fallback-message { 157 display: none; 158} 159 160/* 161 Now let's style the presentation steps. 162 163 We start with basics to make sure it displays correctly in everywhere ... 164*/ 165 166.step { 167 position: relative; 168 width: 900px; 169 padding: 40px; 170 margin: 20px auto; 171 172 -webkit-box-sizing: border-box; 173 -moz-box-sizing: border-box; 174 -ms-box-sizing: border-box; 175 -o-box-sizing: border-box; 176 box-sizing: border-box; 177 178 font-family: 'PT Serif', georgia, serif; 179 font-size: 48px; 180 line-height: 1.5; 181} 182 183/* 184 ... and we enhance the styles for impress.js. 185 186 Basically we remove the margin and make inactive steps a little bit transparent. 187*/ 188.impress-enabled .step { 189 margin: 0; 190 opacity: 0.3; 191 192 -webkit-transition: opacity 1s; 193 -moz-transition: opacity 1s; 194 -ms-transition: opacity 1s; 195 -o-transition: opacity 1s; 196 transition: opacity 1s; 197} 198 199.impress-enabled .step.active { opacity: 1 } 200 201/* 202 These 'slide' step styles were heavily inspired by HTML5 Slides: 203 http://html5slides.googlecode.com/svn/trunk/styles.css 204 205 ;) 206 207 They cover everything what you see on first three steps of the demo. 208*/ 209.slide { 210 display: block; 211 212 width: 900px; 213 height: 700px; 214 padding: 40px 60px; 215 216 background-color: white; 217 border: 1px solid rgba(0, 0, 0, .3); 218 border-radius: 10px; 219 box-shadow: 0 2px 6px rgba(0, 0, 0, .1); 220 221 color: rgb(102, 102, 102); 222 text-shadow: 0 2px 2px rgba(0, 0, 0, .1); 223 224 font-family: 'Open Sans', Arial, sans-serif; 225 font-size: 30px; 226 line-height: 36px; 227 letter-spacing: -1px; 228} 229 230.slide q { 231 display: block; 232 font-size: 50px; 233 line-height: 72px; 234 235 margin-top: 100px; 236} 237 238.slide q strong { 239 white-space: nowrap; 240} 241 242/* 243 And now we start to style each step separately. 244 245 I agree that this may be not the most efficient, object-oriented and 246 scalable way of styling, but most of steps have quite a custom look 247 and typography tricks here and there, so they had to be styles separately. 248 249 First is the title step with a big <h1> (no room for padding) and some 250 3D positioning along Z axis. 251*/ 252 253#title { 254 padding: 0; 255} 256 257#title .try { 258 font-size: 64px; 259 position: absolute; 260 top: -0.5em; 261 left: 1.5em; 262 263 -webkit-transform: translateZ(20px); 264 -moz-transform: translateZ(20px); 265 -ms-transform: translateZ(20px); 266 -o-transform: translateZ(20px); 267 transform: translateZ(20px); 268} 269 270#title h1 { 271 font-size: 190px; 272 273 -webkit-transform: translateZ(50px); 274 -moz-transform: translateZ(50px); 275 -ms-transform: translateZ(50px); 276 -o-transform: translateZ(50px); 277 transform: translateZ(50px); 278} 279 280#title .footnote { 281 font-size: 32px; 282} 283 284/* 285 Second step is nothing special, just a text with a link, so it doesn't need 286 any special styling. 287 288 Let's move to 'big thoughts' with centered text and custom font sizes. 289*/ 290#big { 291 width: 600px; 292 text-align: center; 293 font-size: 60px; 294 line-height: 1; 295} 296 297#big b { 298 display: block; 299 font-size: 250px; 300 line-height: 250px; 301} 302 303#big .thoughts { 304 font-size: 90px; 305 line-height: 150px; 306} 307 308/* 309 'Tiny ideas' just need some tiny styling. 310*/ 311#tiny { 312 width: 500px; 313 text-align: center; 314} 315 316/* 317 This step has some animated text ... 318*/ 319#ing { width: 500px } 320 321/* 322 ... so we define display to `inline-block` to enable transforms and 323 transition duration to 0.5s ... 324*/ 325#ing b { 326 display: inline-block; 327 -webkit-transition: 0.5s; 328 -moz-transition: 0.5s; 329 -ms-transition: 0.5s; 330 -o-transition: 0.5s; 331 transition: 0.5s; 332} 333 334/* 335 ... and we want 'positioning` word to move up a bit when the step gets 336 `present` class ... 337*/ 338#ing.present .positioning { 339 -webkit-transform: translateY(-10px); 340 -moz-transform: translateY(-10px); 341 -ms-transform: translateY(-10px); 342 -o-transform: translateY(-10px); 343 transform: translateY(-10px); 344} 345 346/* 347 ... 'rotating' to rotate quater of a second later ... 348*/ 349#ing.present .rotating { 350 -webkit-transform: rotate(-10deg); 351 -moz-transform: rotate(-10deg); 352 -ms-transform: rotate(-10deg); 353 -o-transform: rotate(-10deg); 354 transform: rotate(-10deg); 355 356 -webkit-transition-delay: 0.25s; 357 -moz-transition-delay: 0.25s; 358 -ms-transition-delay: 0.25s; 359 -o-transition-delay: 0.25s; 360 transition-delay: 0.25s; 361} 362 363/* 364 ... and 'scaling' to scale down after another quater of a second. 365*/ 366#ing.present .scaling { 367 -webkit-transform: scale(0.7); 368 -moz-transform: scale(0.7); 369 -ms-transform: scale(0.7); 370 -o-transform: scale(0.7); 371 transform: scale(0.7); 372 373 -webkit-transition-delay: 0.5s; 374 -moz-transition-delay: 0.5s; 375 -ms-transition-delay: 0.5s; 376 -o-transition-delay: 0.5s; 377 transition-delay: 0.5s; 378} 379 380/* 381 The 'imagination' step is again some boring font-sizing. 382*/ 383 384#imagination { 385 width: 600px; 386} 387 388#imagination .imagination { 389 font-size: 78px; 390} 391 392/* 393 There is nothing really special about 'use the source, Luke' step, too, 394 except maybe of the Yoda background. 395 396 As you can see below I've 'hard-coded' it in data URL. 397 That's not the best way to serve images, but because that's just this one 398 I decided it will be OK to have it this way. 399 400 Just make sure you don't blindly copy this approach. 401*/ 402#source { 403 width: 700px; 404 padding-bottom: 300px; 405 406 /* Yoda Icon :: Pixel Art from Star Wars http://www.pixeljoint.com/pixelart/1423.htm */ 407 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAEYCAMAAACwUBm+AAAAAXNSR0IArs4c6QAAAKtQTFRFsAAAvbWSLUUrLEQqY1s8UYJMqJ1vNTEgOiIdIzYhjIFVLhsXZ6lgSEIsP2U8JhcCVzMsSXZEgXdOO145XJdWOl03LzAYMk4vSXNExr+hwcuxRTs1Qmk+RW9Am49eFRANQz4pUoNMQWc+OSMDTz0wLBsCNVMxa2NBOyUDUoNNSnlEWo9VRGxAVzYFl6tXCggHbLNmMUIcHhwTXkk5f3VNRT8wUT8xAAAACQocRBWFFwAAAAF0Uk5TAEDm2GYAAAPCSURBVHja7d3JctNAFIZRMwRCCGEmzPM8z/D+T8bu/ptbXXJFdij5fMt2Wuo+2UgqxVmtttq5WVotLzBgwIABAwYMGDCn0qVqbo69psPqVpWx+1XG5iaavF8wYMCAAQMGDBgwi4DJ6Y6qkxB1HNlcN3a92gbR5P2CAQMGDBgwYMCAWSxMlrU+UY5yu2l9okfV4bAxUVbf7TJnAwMGDBgwYMCAAbMLMHeqbGR82Zy+VR1Ht81nVca6R+UdTLaU24Ruzd3qM/e4yjnAgAEDBgwYMGDA7AJMd1l/3NRdVGcj3eX/2WEhCmDGxnM7yqygu8XIPjJj8iN/MGDAgAEDBgwYMAuDGb8q0RGlLCHLv1t9qDKWn3vdNHVuEI6HPaxO9Jo3GDBgwIABAwYMmIXBdC9ShGgMk+XnkXUeuGcsP/e1+lhNnZsL/G5Vs3OAAQMGDBgwYMCAWSxMR3SzOmraG5atdy9wZKzb+vg16qyqe2FltbnAgAEDBgwYMGDALAxmTJSuN3WA76rnVca6GTnemGN1WoEBAwYMGDBgwIBZGMxUomy4+xO899V4LAg5Xnc2MGDAgAEDBgwYMGA218Wq+2K1LDqvY9xZu8zN8fICdM6btYABAwYMGDBgwIABMzfH0+pGU5afze2tXebmeAfVz+p8BQYMGDBgwIABAwbMPBzZ+oWmfJrln1273FhkbHzee9WWbw7AgAEDBgwYMGDALAKm43hcdctKgblcPamOhuXnXlY5Xs6bsW4FGyQCAwYMGDBgwIABswiYMceZKgvMo+h8mrHLTdn676rj+FEFoTtHd8MwOxEYMGDAgAEDBgyYRcBM5UhXqiymW3R3c9ARhWO/OmjqfjVZy+xEYMCAAQMGDBgwYBYG073OnCV0RFNhMhaOa9WfKmOB6XjHMN1tQmaAAQMGDBgwYMCA2VWY7vXjz1U4croAzgPztwIDBgwYMGDAgAEDZhswh035NBw59Dww3RgYMGDAgAEDBgwYMJuD6f4tXT7NUqfCdBvZLkxXdgQGDBgwYMCAAQNmt2DGj8WzwAfV/w7T/aq7mxwwYMCAAQMGDBgwuwqTOo7uTwTngflSzQ3TdaJvAwEDBgwYMGDAgAED5gSvgbyo5oHZ4Pc+gwEDBgwYMGDAgAEzhOm+5G0qTGaAAQMGDBgwYMCAAXNaMOcnls3tNwWm+zRzp54NDBgwYMCAAQMGDJh5YNL36k1TLuGvVq+qnKMbS5n7tulT9asCAwYMGDBgwIABA2ZumKuztLnjgQEDBgwYMGDAgNl5mH/4/ltKA6vBNAAAAABJRU5ErkJggg==); 408 background-position: bottom right; 409 background-repeat: no-repeat; 410} 411 412#source q { 413 font-size: 60px; 414} 415 416/* 417 And the "it's in 3D" step again brings some 3D typography - just for fun. 418 419 Because we want to position <span> elements in 3D we set transform-style to 420 `preserve-3d` on the paragraph. 421 It is not needed by webkit browsers, but it is in Firefox. It's hard to say 422 which behaviour is correct as 3D transforms spec is not very clear about it. 423*/ 424#its-in-3d p { 425 -webkit-transform-style: preserve-3d; 426 -moz-transform-style: preserve-3d; /* Y U need this Firefox?! */ 427 -ms-transform-style: preserve-3d; 428 -o-transform-style: preserve-3d; 429 transform-style: preserve-3d; 430} 431 432/* 433 Below we position each word separately along Z axis and we want it to transition 434 to default position in 0.5s when the step gets `present` class. 435 436 Quite a simple idea, but lot's of styles and prefixes. 437*/ 438#its-in-3d span, 439#its-in-3d b { 440 display: inline-block; 441 -webkit-transform: translateZ(40px); 442 -moz-transform: translateZ(40px); 443 -ms-transform: translateZ(40px); 444 -o-transform: translateZ(40px); 445 transform: translateZ(40px); 446 447 -webkit-transition: 0.5s; 448 -moz-transition: 0.5s; 449 -ms-transition: 0.5s; 450 -o-transition: 0.5s; 451 transition: 0.5s; 452} 453 454#its-in-3d .have { 455 -webkit-transform: translateZ(-40px); 456 -moz-transform: translateZ(-40px); 457 -ms-transform: translateZ(-40px); 458 -o-transform: translateZ(-40px); 459 transform: translateZ(-40px); 460} 461 462#its-in-3d .you { 463 -webkit-transform: translateZ(20px); 464 -moz-transform: translateZ(20px); 465 -ms-transform: translateZ(20px); 466 -o-transform: translateZ(20px); 467 transform: translateZ(20px); 468} 469 470#its-in-3d .noticed { 471 -webkit-transform: translateZ(-40px); 472 -moz-transform: translateZ(-40px); 473 -ms-transform: translateZ(-40px); 474 -o-transform: translateZ(-40px); 475 transform: translateZ(-40px); 476} 477 478#its-in-3d .its { 479 -webkit-transform: translateZ(60px); 480 -moz-transform: translateZ(60px); 481 -ms-transform: translateZ(60px); 482 -o-transform: translateZ(60px); 483 transform: translateZ(60px); 484} 485 486#its-in-3d .in { 487 -webkit-transform: translateZ(-10px); 488 -moz-transform: translateZ(-10px); 489 -ms-transform: translateZ(-10px); 490 -o-transform: translateZ(-10px); 491 transform: translateZ(-10px); 492} 493 494#its-in-3d .footnote { 495 font-size: 32px; 496 497 -webkit-transform: translateZ(-10px); 498 -moz-transform: translateZ(-10px); 499 -ms-transform: translateZ(-10px); 500 -o-transform: translateZ(-10px); 501 transform: translateZ(-10px); 502} 503 504#its-in-3d.present span, 505#its-in-3d.present b { 506 -webkit-transform: translateZ(0px); 507 -moz-transform: translateZ(0px); 508 -ms-transform: translateZ(0px); 509 -o-transform: translateZ(0px); 510 transform: translateZ(0px); 511} 512 513/* 514 The last step is an overview. 515 There is no content in it, so we make sure it's not visible because we want 516 to be able to click on other steps. 517 518*/ 519#overview { display: none } 520 521/* 522 We also make other steps visible and give them a pointer cursor using the 523 `impress-on-` class. 524*/ 525.impress-on-overview .step { 526 opacity: 1; 527 cursor: pointer; 528} 529 530 531/* 532 Now, when we have all the steps styled let's give users a hint how to navigate 533 around the presentation. 534 535 The best way to do this would be to use JavaScript, show a delayed hint for a 536 first time users, then hide it and store a status in cookie or localStorage... 537 538 But I wanted to have some CSS fun and avoid additional scripting... 539 540 Let me explain it first, so maybe the transition magic will be more readable 541 when you read the code. 542 543 First of all I wanted the hint to appear only when user is idle for a while. 544 You can't detect the 'idle' state in CSS, but I delayed a appearing of the 545 hint by 5s using transition-delay. 546 547 You also can't detect in CSS if the user is a first-time visitor, so I had to 548 make an assumption that I'll only show the hint on the first step. And when 549 the step is changed hide the hint, because I can assume that user already 550 knows how to navigate. 551 552 To summarize it - hint is shown when the user is on the first step for longer 553 than 5 seconds. 554 555 The other problem I had was caused by the fact that I wanted the hint to fade 556 in and out. It can be easily achieved by transitioning the opacity property. 557 But that also meant that the hint was always on the screen, even if totally 558 transparent. It covered part of the screen and you couldn't correctly clicked 559 through it. 560 Unfortunately you cannot transition between display `block` and `none` in pure 561 CSS, so I needed a way to not only fade out the hint but also move it out of 562 the screen. 563 564 I solved this problem by positioning the hint below the bottom of the screen 565 with CSS transform and moving it up to show it. But I also didn't want this move 566 to be visible. I wanted the hint only to fade in and out visually, so I delayed 567 the fade in transition, so it starts when the hint is already in its correct 568 position on the screen. 569 570 I know, it sounds complicated ... maybe it would be easier with the code? 571*/ 572 573.hint { 574 /* 575 We hide the hint until presentation is started and from browsers not supporting 576 impress.js, as they will have a linear scrollable view ... 577 */ 578 display: none; 579 580 /* 581 ... and give it some fixed position and nice styles. 582 */ 583 position: fixed; 584 left: 0; 585 right: 0; 586 bottom: 200px; 587 588 background: rgba(0,0,0,0.5); 589 color: #EEE; 590 text-align: center; 591 592 font-size: 50px; 593 padding: 20px; 594 595 z-index: 100; 596 597 /* 598 By default we don't want the hint to be visible, so we make it transparent ... 599 */ 600 opacity: 0; 601 602 /* 603 ... and position it below the bottom of the screen (relative to it's fixed position) 604 */ 605 -webkit-transform: translateY(400px); 606 -moz-transform: translateY(400px); 607 -ms-transform: translateY(400px); 608 -o-transform: translateY(400px); 609 transform: translateY(400px); 610 611 /* 612 Now let's imagine that the hint is visible and we want to fade it out and move out 613 of the screen. 614 615 So we define the transition on the opacity property with 1s duration and another 616 transition on transform property delayed by 1s so it will happen after the fade out 617 on opacity finished. 618 619 This way user will not see the hint moving down. 620 */ 621 -webkit-transition: opacity 1s, -webkit-transform 0.5s 1s; 622 -moz-transition: opacity 1s, -moz-transform 0.5s 1s; 623 -ms-transition: opacity 1s, -ms-transform 0.5s 1s; 624 -o-transition: opacity 1s, -o-transform 0.5s 1s; 625 transition: opacity 1s, transform 0.5s 1s; 626} 627 628/* 629 Now we 'enable' the hint when presentation is initialized ... 630*/ 631.impress-enabled .hint { display: block } 632 633/* 634 ... and we will show it when the first step (with id 'bored') is active. 635*/ 636.impress-on-bored .hint { 637 /* 638 We remove the transparency and position the hint in its default fixed 639 position. 640 */ 641 opacity: 1; 642 643 -webkit-transform: translateY(0px); 644 -moz-transform: translateY(0px); 645 -ms-transform: translateY(0px); 646 -o-transform: translateY(0px); 647 transform: translateY(0px); 648 649 /* 650 Now for fade in transition we have the oposite situation from the one 651 above. 652 653 First after 4.5s delay we animate the transform property to move the hint 654 into its correct position and after that we fade it in with opacity 655 transition. 656 */ 657 -webkit-transition: opacity 1s 5s, -webkit-transform 0.5s 4.5s; 658 -moz-transition: opacity 1s 5s, -moz-transform 0.5s 4.5s; 659 -ms-transition: opacity 1s 5s, -ms-transform 0.5s 4.5s; 660 -o-transition: opacity 1s 5s, -o-transform 0.5s 4.5s; 661 transition: opacity 1s 5s, transform 0.5s 4.5s; 662} 663 664/* 665 And as the last thing there is a workaround for quite strange bug. 666 It happens a lot in Chrome. I don't remember if I've seen it in Firefox. 667 668 Sometimes the element positioned in 3D (especially when it's moved back 669 along Z axis) is not clickable, because it falls 'behind' the <body> 670 element. 671 672 To prevent this, I decided to make <body> non clickable by setting 673 pointer-events property to `none` value. 674 Value if this property is inherited, so to make everything else clickable 675 I bring it back on the #impress element. 676 677 If you want to know more about `pointer-events` here are some docs: 678 https://developer.mozilla.org/en/CSS/pointer-events 679 680 There is one very important thing to notice about this workaround - it makes 681 everything 'unclickable' except what's in #impress element. 682 683 So use it wisely ... or don't use at all. 684*/ 685.impress-enabled { pointer-events: none } 686.impress-enabled #impress { pointer-events: auto } 687 688/* 689 There is one funny thing I just realized. 690 691 Thanks to this workaround above everything except #impress element is invisible 692 for click events. That means that the hint element is also not clickable. 693 So basically all of this transforms and delayed transitions trickery was probably 694 not needed at all... 695 696 But it was fun to learn about it, wasn't it? 697*/ 698 699/* 700 That's all I have for you in this file. 701 Thanks for reading. I hope you enjoyed it at least as much as I enjoyed writing it 702 for you. 703*/ 704 705