Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
540 lines (472 loc) · 30.9 KB
/
Copy pathindex.html
File metadata and controls
540 lines (472 loc) · 30.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSS Performance & What is the Browser doing?</title>
<meta name="description" content="Talk originally made for Confoo 2016">
<meta name="author" content="Sarah Etter">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/white.css" id="theme">
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-50111242-1', 'sarahetter.com');
ga('send', 'pageview');
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h1>CSS Performance & What is the Browser doing?</h1>
<p>
<small>by <a href="http://sarahetter.com">Sarah Etter</a> / <a href="http://twitter.com/SarahEtter_">@SarahEtter_</a></small>
</p>
</section>
<section>
<h1>Sarah Etter</h1>
<br>
<a href="http://sarahetter.com">sarahetter.com</a>
<br>
<a href="http://twitter.com/SarahEtter_">@SarahEtter_</a>
<br>
<a href="mailto:sarah@sarahetter.com">sarah@sarahetter.com</a>
<br><br><br><br>
<img src="img/territoriallogo.svg" style="max-width:25%;">
<aside class="notes">
<p>Have a few chapters to this talk. First browser works, then css optimizing, then devtools</p>
<p>Won't talk about differences between browsers, just keep in mind that each one has their own implementation, and differ slightly</p>
</aside>
</section>
<section>
<h2>Why build performant sites?</h2>
<a href="https://wpostats.com/">https://wpostats.com/</a>
<aside class="notes">
This is a site with blog entries about tons of sites that lowered page latency/load time & saw a positive output in regards to conversions
<p>Makes you, your boss, your client money</p>
</aside>
</section>
<section>
<section>
<h2>Object Models</h2>
<div class="object-model">DOM</div>
<div class="object-model">CSSOM</div>
<aside class="notes">
<p>Once the browser loads in your HTML & CSS, it begins building objects that represent your site.</p>
<p>First off - DOM (Document Object Model). This is a tree structure that, if you have done any JS programming, you are very familiar with. Each element in your HTML is a node, and nodes have children. The DOM should be identical between browsers, however if you have incorrectly nested HTML each browser has a slightly different way of parsing through & attempting to correct errors, so there may be slight differences.</p>
<p>Once done dom, it creates the CSS Object Model. This is a model that is much like the DOM, but for CSS. It is a tree structure. It contains objects like: StyleSheetList, CSSStyleSheet, CSSStyleRule.</p>
</aside>
</section>
<section>
<h2>Tree Structure</h2>
<img src="img/tree.gif">
</section>
</section>
<section>
<h2>Object Models</h2>
<div class="object-model">DOM</div>
<div class="object-model">CSSOM</div>
<div></div>
<div class="object-model">Render Tree</div>
<aside class="notes">
<p>After the browser has finished making the DOM and the CSSOM, it combines them both into another model called the Render Tree</p>
<p>The render tree is created by going through the DOM (things that actually exist on the website), and adding the CSS rules from the CSSOM to those DOM nodes.</p>
<p>Render tree doesn’t contain things that are hidden by CSS (display:none)</p>
</aside>
</section>
<section>
<section>
<h2>Render Tree - Digging Deeper</h2>
<ul>
<li>Style Sharing</li>
<li>CSS Rule Hash Tables</li>
<li>Ancestor Filters</li>
<li>Fast Path</li>
</ul>
<aside class="notes">
<p>How the render tree is created is fairly important.
The dom isn’t matched against every single CSS rule, because that would be insanely slow.
The browser uses different intermediate sorts / searches and data structures to make this matching faster.</p>
<p>A data structure is a way of organizing data. There are many different types of data structures, and they each have a different way of making the task of dealing with data more efficient.</p>
<p>Each browser uses any or all of these, and their exact implementation may be different. There may be some other efficiencies added!</p>
<p><strong>Style Sharing</strong> - simply means that a browser figures out which DOM elements share the exact same styles (for example, two li’s in the same list). This saves having to do the exact same work more than once.</p>
</aside>
</section>
<section>
<h2>CSS Rule Hash Tables</h2>
<img src="img/hashtable.png">
<aside class="notes">
<p><strong>CSS Rule Hash tables</strong>. - A hash table (simply put) is an associative array. When creating a hash table, you feed the element you are adding into a hash function, which calculates an index to place that element at in the array. When matching elements from the DOM to this hashtable, you just do that backwards. SO find hash, and only look at elements in that spot in the array. Saves from looking at every other element in other indices.</p>
<p>Sometimes there are hash tables within hashtables</p>
</aside>
</section>
<section>
<h2>Ancestor Filters</h2>
<img src="img/bloomfilter.png">
<small>By David Eppstein - self-made, originally for a talk at WADS 2007, Public Domain, https://commons.wikimedia.org/w/index.php?curid=2609777</small>
<aside class="notes">
<p>Bloom filter tests whther a CSS rule is a member of the set of rules that match the element you are currently testing</p>
<p><strong>Ancestor Filters</strong> - the browser checks to see if this is part of a set. It uses something called a Bloom Filter. A bloom filter uses a large array, and sets all elements in array to one bit - 0. Then, when running elements through the filter, it uses another type of hash function, which gets a number of indices. Then the original bits in the index at those indices are set to 1. So when checking against this filter, you can know for sure if your element matches - if all of it’s hash indexes are 1, then it may be in the set. If any of them are 0, then it is definitely not in the set. This narrows down how many selectors the browser has to compare against.</p>
</aside>
</section>
<section>
<h2>Fast Path</h2>
<aside class="notes">Once browser has narrowed the amt of selectors, does a non recursive pass and matches selectors</aside>
</section>
</section>
<section>
<h2>Rendering</h2>
<div class="object-model">Layout</div>
<div class="object-model">Paint</div>
<div class="object-model">Composite</div>
<aside class="notes">
<p>Once render tree is done, the browser does the actual rendering. These steps are Layout, Paint, and Composite.</p>
</aside>
</section>
<section>
<h2>Layout (aka Reflow)</h2>
<ul>
<li>Creates the layout of the site</li>
<li>Takes all positioning and sizing rules and creates a box-only layout of the site.</li>
<li>Calculates number of lines for text and uses line height</li>
<li>Recursive process</li>
</ul>
<aside class="notes">
<p><strong>Recursive process</strong> -
First finds width of parent, then loops down to the deepest node, and finds it’s size & positioning, then goes up through the tree.</p>
<p>This is why when you have a fixed height and width on a parent, if the contents are larger they overflow.</p>
<p>The deeper your DOM, the longer this process takes.</p>
</aside>
</section>
<section>
<h2>Layout Visualization</h2>
<iframe src="https://www.youtube.com/embed/ZTnIxIA5KGw" frameborder="0" allowfullscreen></iframe>
<aside class="notes">
At the end - the flash, there is a layout invalidation, so it has to reflow
</aside>
</section>
<section>
<h2>Paint</h2>
<ul>
<li>Browser creates layers and adds the colours to pixels on these layers.</li>
<li>Not actually on the page yet.</li>
<li>Browser sends layer to the CPU or in some cases GPU</li>
<li>Processor creates the texture (bitmap final image) to be displayed on the page</li>
</ul>
<aside class="notes">
<p>GPU - 3d transforms, anything with will-change CSS property set. Makes rendering faster</p>
<p>will-change - added to hint to browsers that this might be a good thing to send to GPU for faster rendering</p>
<p>Don't put will-change on everything, as that has the same issues has having everything go to CPU. </p>
</aside>
</section>
<section>
<h2>Composite</h2>
<ul>
<li>Taking the painted layers and placing them on the previously calculated layout.</li>
</ul>
<aside class="notes">
This is the least computationally heavy action.
</aside>
</section>
<section>
<h2>Layout Invalidations</h2>
<ul>
<li>Manipulating DOM tree</li>
<li>Hiding things (adding display: none)</li>
<li>Resizing window</li>
<li>Changing the font</li>
<li>Adding or removing a stylesheet</li>
<li>Content changes</li>
<li>Manipulating the class attribute</li>
<li>Getting offsetWidth and offsetHeight </li>
<li>And more...</li>
</ul>
<aside class="notes">
<p>So whenever you do these things, the browser will have a higher workload, and your website may encounter some “jank” or lower performance.</p>
<p>The browser has to go through layout, paint, and composite again..</p>
</aside>
</section>
<section>
<h2>So what does this all mean?</h2>
<div class="fragment">
<pre><code class="hljs css">
.link {
color: blue;
}
.tagLi .tagB a.TagA.link {
color: blue;
}
div.wrapper > div.tagDiv > div.tagDiv.layer2 >
ul.tagUL > li.tagLi > b.tagB > a.TagA.link {
color: blue;
}
</code></pre>
</div>
<aside class="notes">
<p>As far as your stylesheet structure, The Browser is doing most of the work for you.</p>
<p>Because of the work done & efficiencies added at the Render Tree creating stage, it is impossible to tell how each of your css rules will be parsed.</p>
<p>And as it turns out, the time it takes the browser to render different css selectors is negligible. (Ben Frain did a comparison in early 2014 with 20 diff selectors, and the biggest difference in time with a humonguous DOM (5000 nested elements) 14 ms. .</p>
<p>first selector - 50.4 ms. second - 50.2 ms, third - 64.6 ms</p>
<p>Difference is in Chrome. diff between first two is easily within margin of error of the calculation method used</p>
<p>Different browsers had different slowest selector</p>
<p>It isn’t your job to write the CSS structure for the browser. It’s the browser’s job to make it efficient. Each engine does things a bit differently, so trying to guess how it will split up your selectors is futile.</p>
<p>However, one is way more semantic and easier to write. Don't JUST write it because it's faster, write it because it makes sense.</p>
</aside>
</section>
<section>
<img src="img/paulIrish.png">
<aside class="notes">paul is on google's chrome team</aside>
</section>
<section>
<h2>So what can I do?</h2>
<ul>
<li>Two categories:
<ol>
<li>Load-time Optimization</li>
<li>After Load Optimization</li>
</ol>
</li>
</ul>
<aside class="notes">
There are limited things you can do to help load behaviour, but the major thing to know about CSS performance
is that it's not just about loading quickly, it's about how your site actually feels while using it. When there
are 'hiccups' in rendering, this is called jank. For example: when images load slowly, and layout is triggered, it makes
your site feel clunky.
</aside>
</section>
<section>
<section>
<h2>Load-time Optimization</h2>
<ul>
<li>CDN</li>
<li>Don't use @import</li>
<li>Browser Caching</li>
<li>Gzip</li>
<li>Stylesheet Size</li>
<li>Critical CSS</li>
</ul>
<aside class="notes">
Setting expires headers to css file (setup in web server)
<br> mod_expires in apache,
</aside>
</section>
<section>
<h3>Stylesheet Size</h3>
<ul>
<li>UnCSS - npm package that uses PhantomJS</li>
<ul><li><small><a href="https://github.com/giakki/uncss">https://github.com/giakki/uncss</a></small></li></ul>
<li>Less specific, more modular code (Easier to maintain, too!)</li>
<li>In general: Write as little CSS as possible</li>
<li>DRY</li>
<li>Minify</li>
</ul>
<aside class="notes">
<p>Avail in both grunt & gulp flavours</p>
<p>PhantomJS - headless browser. Executes through command line, doesn't output anything to a GUI. Webkit engine</p>
<p>extra css is added to cssom, so not only saving on DL time</p>
<p>DRY - as always, if you are seeing repetitive code, you should be abstracting it out</p>
</aside>
</section>
<section>
<h3>Critical CSS</h3>
<ul>
<li>Inline above the fold CSS</li>
<li>critical npm package - finds critical CSS for you
<ul><li><small><a href="https://www.npmjs.com/package/critical-css">https://www.npmjs.com/package/critical-css</a></small></li></ul></li>
<li>Warning: inline won’t leverage browser caching</li>
</ul>
<aside class="notes">
<p>include all of the CSS that is required to style the top section of your site</p>
<p>Inline means no second request, no latency</p>
</aside>
</section>
</section>
<section>
<section>
<h2>After Load Optimization</h2>
<p>Considerations:</p>
<ul>
<li>Scrolling</li>
<li>Animations</li>
<li>Interactions</li>
<li><a href="http://csstriggers.com/">http://csstriggers.com/</a></li>
</ul>
</section>
<section>
<h2>Scrolling</h2>
<ul>
<li>Browser needs to be painting during scroll</li>
</ul>
<aside class="notes">
<ul>
<li>Parallax - large portion needs repainting</li>
<li>Requesting offsetTop - causes reflow</li>
<li>position: fixed;</li>
</ul>
</aside>
</section>
<section>
<h2>Animations</h2>
<ul>
<li>CSS animations/transitions preferred!</li>
<li>Don't use setTimeout</li>
<li>requestAnimationFrame(function())</li>
<li>transform: translate(); instead of top/right/bottom/left</li>
</ul>
<aside class="notes">
css animations - just smoother, better optimized.<br>
setTimeout - bad for battery, isn't synched with paint cycles <br>
requestAnimationFrame -allows browser to set exactly when best time is. <br>
transform translate only triggers composite, so no layout or paint are needed.
</aside>
</section>
<section>
<h2>Interaction</h2>
<ul>
<li>Beware of layout invalidations</li>
</ul>
<aside class="notes">
<p>Interactions - CSS invalidation!</p>
<p>Click on nav, if add “active” class to whole body, then ALL CSS is invalidated & need to do not only layout, but layout, paint, composite again. Want to only invalidate the smallest chunk possible.</p>
<p>Some frameworks add classes to body to change state - BAD BAD BAD</p>
</aside>
</section>
</section>
<section>
<h2>Expensive Styles</h2>
<ul>
<li>Some styles take a slightly longer time to render initially
<ul>
<li>box-shadow</li>
<li>border-radius</li>
<li>transform</li>
<li>CSS filters</li>
</ul>
</li>
</ul>
<aside class="notes">
<p>Notice that these are all fairly new properties. Render time may improve, as well as it's important to just use these
sparingly.</p>
</aside>
</section>
<section>
<section>
<h2>Chrome Devtools Monitoring</h2>
<ul>
<li>Rendering Tab</li>
<li>Timeline</li>
</ul>
</section>
<section>
<h3>Rendering Tab</h3>
<ul>
<li>Enable Paint Flashing</li>
<li>Show FPS meter</li>
<li>Show scrolling perf issues</li>
<li>Show layer borders</li>
</ul>
<aside class="notes">
<p>Enable paint flashing - click on, go to http://www.cnn.com/ (Entire Window flashes, indicating a lot of full invalidation) VS. https://www.reddit.com/ - can see when individual things are painted on load. Then show difference in scrolling, how reddit flashes and cnn doesn’t. CNN scroll is a much better, less janky experience, even though reddit doesn’t have a lot to it - just text, small thumbnails.</p>
<p>highlighted area should be small. bigger area, slower it’ll be.</p>
<p>Show FPS meter - looking for 60 FPS</p>
<p>Show scrolling perf issues - http://www.nytimes.com/ (shows mousewheel event listener) in top corner</p>
<p>Show layer borders - show in own presentation. Want to make layers small. Also notice that paint doesn't occur on animation, but on end of state when another class is added.</p>
</aside>
</section>
<section>
<h3>Timeline</h3>
<ul>
<li>Record Timeline</li>
<li>Watch for long frames</li>
<li>Diagnose the issue</li>
</ul>
<aside class="notes">
http://pitchfork.com/features/cover-story/reader/daft-punk/<br>
</aside>
</section>
</section>
<section>
<h1>Questions?</h1>
</section>
<section>
<a href="http://sarahetter.com">sarahetter.com</a>
<br>
<a href="http://twitter.com/SarahEtter_">@SarahEtter_</a>
<br>
<a href="mailto:sarah@sarahetter.com">sarah@sarahetter.com</a>
<br>
<a href="http://sarahetter.com/slides/cssbrowser">http://sarahetter.com/slides/cssbrowser</a>
</section>
<section>
<ul class="super-small">
<li><a href="http://stackoverflow.com/questions/19330731/tree-implementation-in-java-root-parents-and-children">http://stackoverflow.com/questions/19330731/tree-implementation-in-java-root-parents-and-children</a></li>
<li><a href="http://www.smashingmagazine.com/2015/08/understanding-critical-css/?utm_content=buffer560ad&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer">http://www.smashingmagazine.com/2015/08/understanding-critical-css/?utm_content=buffer560ad&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer</a></li>
<li><a href="http://csswizardry.com/2012/05/keep-your-css-selectors-short/">http://csswizardry.com/2012/05/keep-your-css-selectors-short/</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/">http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/</a></li>
<li><a href="https://web.archive.org/web/20150907190404/http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/">https://web.archive.org/web/20150907190404/http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/</a></li>
<li><a href="http://www.adobe.com/inspire/2013/05/irish-fast-css-on-mobile.html">http://www.adobe.com/inspire/2013/05/irish-fast-css-on-mobile.html</a></li>
<li><a href="https://github.com/giakki/uncss">https://github.com/giakki/uncss</a></li>
<li><a href="http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/">http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/</a></li>
<li><a href="http://www.dayofjs.com/videos/22158462/web-browsers_alex-russel">http://www.dayofjs.com/videos/22158462/web-browsers_alex-russel</a></li>
<li><a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a">https://gist.github.com/paulirish/5d52fb081b3570c81e3a</a></li>
<li><a href="https://dl.dropboxusercontent.com/u/39519/talks/cssperf/index.html">https://dl.dropboxusercontent.com/u/39519/talks/cssperf/index.html</a></li>
<li><a href="https://www.youtube.com/watch?v=SmE4OwHztCc">https://www.youtube.com/watch?v=SmE4OwHztCc</a></li>
<li><a href="http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/">http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/</a></li>
<li><a href="http://www.paulirish.com/2011/dom-html5-css3-performance/">http://www.paulirish.com/2011/dom-html5-css3-performance/</a></li>
<li><a href="http://csstriggers.com/">http://csstriggers.com/</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/speed/scrolling/">http://www.html5rocks.com/en/tutorials/speed/scrolling/</a></li>
<li><a href="https://developers.google.com/web/fundamentals/performance/rendering/?hl=en">https://developers.google.com/web/fundamentals/performance/rendering/?hl=en</a></li>
<li><a href="https://aerotwist.com/blog/pixels-are-expensive/">https://aerotwist.com/blog/pixels-are-expensive/</a></li>
<li><a href="http://www.kellegous.com/j/2013/01/26/layout-performance/">http://www.kellegous.com/j/2013/01/26/layout-performance/</a></li>
<li><a href="http://www.paulirish.com/2015/advanced-performance-audits-with-devtools/">http://www.paulirish.com/2015/advanced-performance-audits-with-devtools/</a></li>
<li><a href="https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count">https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count</a></li>
<li><a href="https://css-tricks.com/tale-of-animation-performance/">https://css-tricks.com/tale-of-animation-performance/</a></li>
<li><a href="https://developer.chrome.com/devtools/docs/timeline">https://developer.chrome.com/devtools/docs/timeline</a></li>
<li><a href="http://calendar.perfplanet.com/2013/the-runtime-performance-checklist/">http://calendar.perfplanet.com/2013/the-runtime-performance-checklist/</a></li>
<li><a href="https://addyosmani.com/blog/performance-optimisation-with-timeline-profiles/">https://addyosmani.com/blog/performance-optimisation-with-timeline-profiles/</a></li>
</ul>
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
transition: 'slide', // none/fade/slide/convex/concave/zoom
// Optional reveal.js plugins
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true },
{ src: 'plugin/notes/notes.js', async: true }
]
});
</script>
</body>
</html>