This repository has been archived by the owner on Jul 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
index.html
903 lines (749 loc) · 35.5 KB
/
index.html
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
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
<!DOCTYPE html>
<html lang="en">
<head>
<title>BlitzTricks — CSS tricks to improve your eBooks</title>
<meta charset="utf-8">
<meta name="description" content="A collection of CSS snippets to do progressive enhancement and achieve better typography, layout and UX in eBooks.">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/styles.css" />
<link rel="stylesheet" type="text/css" href="css/print.css" media="print" />
<!-- Favicon -->
<link rel="shortcut icon" href="assets/favicon.ico" type="image/x-icon">
<link rel="icon" href="assets/favicon.ico" type="image/x-icon">
<!-- Google -->
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#FAFAFA">
<!-- Apple -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="BlitzTricks">
<link rel="apple-touch-icon" href="assets/icons/icon-256x256.png">
<!-- MS -->
<meta name="msapplication-TileImage" content="assets/icons/icon-256x256.png">
<meta name="msapplication-TileColor" content="#FAFAFA">
<meta name="application-name" content="BlitzTricks">
</head>
<body>
<header>
<img class="header-icon" alt="" src="assets/logo.svg"/>
<h1>Blitz ebook Tricks</h1>
<p class="lead"><strong class="banner">As of July 1, 2020 this web app is no longer maintained.</strong></p>
<p class="lead">A collection of <abbr title="Cascading Style Sheets">CSS</abbr> snippets to do progressive enhancement and achieve better typography, layout and <abbr title="User Experience">UX</abbr> in eBooks.</p>
<p class="lead">Those snippets are primarily intended for <abbr title="Electronic Publication">EPUB</abbr>3 though some will work in ePub2 and/or Kindle.</p>
</header>
<nav class="menu">
<ol>
<li><a href="#typography">Typo</a></li>
<li><a href="#layout">Layout</a></li>
<li><a href="#images">Images</a></li>
<li><a href="#misc">Misc</a></li>
</ol>
</nav>
<main>
<section class="category" id="typography">
<h2>Typography</h2>
<section class="trick" id="typo-lineheight">
<div class="wrapper">
<h3>Add line-height to body</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>body {
line-height: 1.5;
}
body * {
line-height: inherit;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If you add an explicit line-height to elements, your <abbr title="Cascading Style Sheets">CSS</abbr> may break Kobo’s – and possibly others’ – user setting. By adding it to <code>body</code> and letting elements inherit from it, this problem is solved.</p>
<p class="details-para">If you are targeting Kindle, please note the Publishing Guidelines recommends against setting a <code>line-height</code> on <code>body</code>.</p>
</div>
</div>
</section>
<section class="trick" id="typo-kindle-lineheight">
<div class="wrapper">
<h3>Don’t define a line-height value which is less than 1.2</h3>
<div class="tags"><span class="tag">Kindle Format 8</span></div>
<div class="code-snippet">
<pre><code>element {
line-height: 1.2;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">As stated in versions of the <a href="https://kindlegen.s3.amazonaws.com/AmazonKindlePublishingGuidelines.pdf">Kindle Publishing Guidelines</a> prior to 2018.2, “to ensure pagination, the Kindle software does not honor line-height value less than <code>1.2em</code> or <code>120%</code>.”</p>
<p class="details-para">In other words, elements for which line-height is less than <code>1.2</code> will be applied the default’s line-height, which is <code>1.75</code> on most Kindle devices.</p>
</div>
</div>
</section>
<section class="trick" id="typo-hyphens">
<div class="wrapper">
<h3>Disable hyphens</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle Format X</span></div>
<div class="code-snippet">
<pre><code>element {
adobe-hyphenate: none;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
-epub-hyphens: none;
hyphens: none;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Usually, some elements like headings, centered text, etc. are not hyphenated.</p>
<p class="details-para">Those declarations should cover all self-respecting Reading Systems.</p>
</div>
</div>
</section>
<section class="trick" id="typo-hyphenation">
<div class="wrapper">
<h3>Improve hyphenation</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>element {
-webkit-hyphenate-limit-before: 3;
-webkit-hyphenate-limit-after: 2;
-ms-hyphenate-limit-chars: 6 3 2;
hyphenate-limit-chars: 6 3 2;
-webkit-hyphenate-limit-lines: 2;
hyphenate-limit-lines: 2;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">When you set hyphens to <code>auto</code>, extra declarations can be set to improve hyphenation for your language.</p>
<p class="details-para">You can indeed set the minimum number of letters a word must contain to be hyphenated, and the minimum number of letters which should be before and after the hyphen.</p>
<p class="details-para">Finally, you can control the maximum number of consecutive lines for which hyphenation must happen. <a href="http://webtypography.net/2.4.3">As Bringhurst advised</a>, “avoid more than three consecutive hyphenated lines.”</p>
</div>
</div>
</section>
<section class="trick" id="typo-align">
<div class="wrapper">
<h3>Declare text-align for elements which should be left-aligned</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>element {
text-align: left;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If some elements like headings should be left-aligned, make sure to declare <code>text-align</code>.</p>
<p class="details-para">Indeed, those elements will be justified if you don’t and the user sets full justification. Word-spacing will then be adjusted so that the text falls flush with both margins, which can result in terrible typography.</p>
</div>
</div>
</section>
<section class="trick" id="typo-sup">
<div class="wrapper">
<h3>Prevent sub- and superscript from affecting line-height</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>sub {
font-size: 0.675em;
line-height: 1.2;
vertical-align: sub;
vertical-align: -20%;
}
sup {
font-size: 0.675em;
line-height: 1.2;
vertical-align: super;
vertical-align: 35%;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Sub- and superscript will affect line-height if you just use their dedicated keyword for <code>vertical-align</code>.</p>
<p class="details-para">By decreasing <code>line-height</code> to the minimum value Kindle supports (i.e. <code>1.2</code>) and using <code>%</code> for <code>vertical-align</code>, we solve this problem and can vertically-align sub- and superscript more accurately.</p>
</div>
</div>
</section>
<section class="trick" id="typo-legibility">
<div class="wrapper">
<h3>Improve legibility</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>body {
font-kerning: normal;
font-variant: common-ligatures oldstyle-nums proportional-nums;
font-feature-settings: "kern", "liga", "clig", "onum", "pnum";
}
h1, h2, h3 {
font-variant: common-ligatures lining-nums proportional-nums;
font-feature-settings: "kern", "liga", "clig", "lnum", "pnum";
}
table {
font-variant-numeric: lining-nums tabular-nums;
font-feature-settings: "kern", "lnum", "tnum";
}
code {
font-variant: no-common-ligatures lining-nums;
font-feature-settings: "kern" 0, "liga" 0, "clig" 0, "lnum";
}
.fraction {
font-variant-numeric: diagonal-fractions;
font-feature-settings: "frac";
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">OpenType features can dramatically improve the legibility of an eBook. Although not all default fonts provided by Reading Systems support all those features, you can still benefit from them.</p>
<p class="details-para">The <code>font-feature-settings</code> property is a low-level feature designed to handle special cases where no other way to enable or access an OpenType font feature exists, which is why you should prefer <code>font-variant</code> and its associated longhand properties.</p>
<p class="details-para">Please note <code>font-feature-settings</code> doesn’t inherit values from the parent element but resets them.</p>
<p class="details-para">For a complete list of features, <a href="https://helpx.adobe.com/typekit/using/open-type-syntax.html">visit this Typekit help page</a>.</p>
</div>
</div>
</section>
<section class="trick" id="typo-smallcaps">
<div class="wrapper">
<h3>Use real small capitals</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>element {
font-variant: small-caps;
}
@supports not (font-variant-caps: small-caps) {
element {
font-variant: normal;
font-feature-settings: "smcp", "onum", "pnum";
}
}
@supports (font-variant-caps: small-caps) {
element {
font-variant: normal;
font-variant-caps: small-caps;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">The <code>font-variant:small-caps</code> property creates fake small caps. This can turn an enjoyable book into a mediocre experience since you can tell they are fake in the blink of an eye.</p>
<p class="details-para">By using OpenType Features, we can use real small caps the typeface designer took special care getting right.</p>
<p class="details-para">Please note that if the font doesn’t support this feature, it will fall back to fake small caps.</p>
</div>
</div>
</section>
<section class="trick" id="typo-semantic_asterism">
<div class="wrapper">
<h3>Use semantic asterisms and make them reflowable</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>hr.asterism {
height: 1.5em;
background: transparent url("../Images/asterism.svg") no-repeat center;
background-size: 2.5em 1.25em;
overflow: hidden;
page-break-inside: avoid;
break-inside: avoid;
}
@supports not ((page-break-inside: avoid) and (break-inside: avoid)) {
hr.asterism {
-webkit-column-break-inside: avoid;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Asterisms are context changes, thus <a title="EPUB 3 Accessibility Guidelines — Context Breaks" href="https://idpf.github.io/a11y-guidelines/content/xhtml/context.html">you should use <code>hr</code></a>.</p>
<p class="details-para">Problem is <code>hr</code> can’t contain anything so the only solution is to use a background image.</p>
<p class="details-para">Your best option is <abbr title="Scalable Vector Graphics">SVG</abbr> since it manages transparency, reflow without a loss in quality, can be designed to be compatible with night modes, etc.</p>
<p class="details-para">Reading Systems which don’t support <code>background-size</code> will fall back to the <code>width</code>, <code>height</code> and <code>viewbox</code> attributes in your SVG so don’t get rid of them.</p>
</div>
</div>
</section>
<section class="trick" id="typo-fake_asterism">
<div class="wrapper">
<h3>Fake asterisms (context change)</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code><div class="asterism" role="separator" aria-label="Interlude">
* * *
</div>
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Sometimes you can’t use semantic asterisms (<code>background-image</code> for <code>hr</code>) and adding it with <code>hr:before</code> may prove to be problematic for accessibility.</p>
<p class="details-para">In that case, the ARIA <code>role</code> and <code>aria-label</code> attributes may come in handy.</p>
<p class="details-para"><a href="https://www.w3.org/TR/wai-aria/roles#separator">The <code>separator</code> role</a> tells Reading Systems the <code>div</code> is intended to be a context change (<code>hr</code>) and the <code>aria-label</code> will override the text inside it for Text to Speech.</p>
<p class="details-para">If you intend to mimick how <code>hr</code> will typically be handled for selection and copy, don’t forget to disable user’s selection though (see “<a href="#layout-numbering">Create an automated numbering system</a>” trick).</p>
</div>
</div>
</section>
<section class="trick" id="typo-links">
<div class="wrapper">
<h3>Force the color of links to be text’s</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>a.text-color {
color: inherit;
-webkit-text-fill-color: inherit;
}</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Sometimes there are so many links on a page that styling them using colors may disrupt the reading experience. <a title="W3C wiki — Styling Links" href="https://www.w3.org/wiki/Styling_lists_and_links#Styling_Links">As long as users can tell it’s a link</a>, you should be OK.</p>
<p class="details-para">If you want links to be the same color as text, you can inherit <code>color</code>. The <code>-webkit-text-fill-color</code> property forces iBooks to use the text’s color in night mode.</p>
<p class="details-para">While this snippet should work OK in the Kindle Format 8, it won’t in Kindle Format X, and a blue color will be forced for links – there’s currently no known trick to get around this.</p>
</div>
</div>
</section>
</section>
<section class="category" id="layout">
<h2>Layout</h2>
<section class="trick" id="layout-block">
<div class="wrapper">
<h3>Make HTML5 tags behave as expected in legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr></h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>article, aside, figure, figcaption,
footer, header, main, nav, section {
display: block;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Did you know most of <abbr title="HyperText Markup Language">HTML</abbr> elements have a default <code>display</code> value of <code>inline</code>? It’s up to browsers to set some elements to <code>block</code>.</p>
<p class="details-para">Since the legacy RMSDK is not supposed to support HTML5, you must set grouping elements to <code>block</code> in your style sheet.</p>
</div>
</div>
</section>
<section class="trick" id="layout-margin_reflow">
<div class="wrapper">
<h3>Prevent horizontal margins to reflow with font-size</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>element-1 {
margin-left: {number}%;
}
element-2 {
padding-left: {number}%;
padding-right: {number}%;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If you use <code>em</code> for horizontal margins, they will increase/decrease with the <code>font-size</code> user setting. This implies that the bigger the text is set, the smaller its container will be – it should be the opposite.</p>
<p class="details-para">By using <code>%</code> for horizontal margins and paddings, Reading Systems will use the width of the page or parent container to compute them, not the current <code>font-size</code>.</p>
</div>
</div>
</section>
<section class="trick" id="layout-center">
<div class="wrapper">
<h3>Center a block element in legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr></h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>element {
width: {number}%;
margin-left: ((100 - {number}) / 2 )%;
margin-right: ((100 - {number}) / 2 )%;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Legacy RMSDK doesn’t really support the <code>auto</code> value for <code>margin</code>. As a matter of fact, it maps <code>auto</code> to <code>0</code>, which is <a href="http://www.idpf.org/epub/20/spec/OPS_2.0.1_draft.htm#Section3.3">allowed in a footnote of the <abbr title="Electronic Publication">ePub</abbr>2 specification</a>.</p>
<p class="details-para">In other words, if you want to center an element, you should declare a <code>width</code> then substract it from <code>100</code> and divide it by <code>2</code> to get your horizontal margins.</p>
<p class="details-para">If your element is <code>80%</code> then each margin will be <code>(100-80)/2</code> or <code>10%</code>.</p>
</div>
</div>
</section>
<section class="trick" id="layout-break">
<div class="wrapper">
<h3>Do not rely on page-breaks</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>element {
page-break-inside: avoid;
break-inside: avoid;
}
@supports not ((page-break-inside: avoid) and (break-inside: avoid)) {
element {
-webkit-column-break-inside: avoid;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">CSS break is a strange beast. But what’s important is that we shouldn’t only rely on paged media.</p>
<p class="details-para">Modern Reading Systems will typically use CSS multi-columns to fake pagination since browsers don’t implement paged media, which means <code>page-break-*</code> is <a href="https://caniuse.com/#feat=multicolumn">not necessarily aliased</a> to <code>column-break-*</code>. And <code>page-break-*</code> itself <a href="https://drafts.csswg.org/css-break-3/#break-between">is destined to become an alias</a> for <code>break-*</code> at some point. For maximum compatibility, we must therefore use all three.</p>
<p class="details-para">The feature query (<code>@supports</code>) allows us to get around some bug in iBooks. At some point, declaring <code>-webkit-column-break-inside</code> in the same rule as <code>page-break-inside</code> would indeed result in both styles being ignored.</p>
</div>
</div>
</section>
<section class="trick" id="layout-pagebreak">
<div class="wrapper">
<h3>Prefer page-break-after to page-break-before</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>element {
page-break-after: always;
break-after: always;
}
@supports not ((page-break-after: always) and (break-after: always)) {
element {
-webkit-column-break-after: always;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">For some reason, it looks like <code>page-break-after:always</code> has got slightly better support than <code>page-break-before:always</code> in some Reading Systems.</p>
<p class="details-para">As stated in <a href="https://help.apple.com/itc/booksassetguide/e3?lang=en#/itc04314e64a">iBooks Asset Guide</a>, “if you include page breaks to mark a chapter break, use <code>page-break-after</code> to create a break at the end of a chapter, not <code>page-break-before</code> to insert the break at the beginning of the chapter. This modification improves performance with the table of contents.”</p>
<p class="details-para">In any case, don’t use both since it will create a blank page in some Reading Systems.</p>
</div>
</div>
</section>
<section class="trick" id="layout-table">
<div class="wrapper">
<h3>Fix the layout of tables</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>table {
table-layout: fixed;
}
th.third {
width: 33%;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">By default, you can’t really tell how Reading Systems will compute the width of tables’ columns. All you know is that they will compute those widths depending on their cells’ contents.</p>
<p class="details-para"><a href="https://css-tricks.com/fixing-tables-long-strings/">You can force a width for each column</a> by using <code>table-layout:fixed</code> then declaring a <code>width</code> for each element in the first line of the table.</p>
<p class="details-para">Reading Systems will now use the width specified for those elements to compute the width of each column.</p>
</div>
</div>
</section>
<section class="trick" id="layout-numbering">
<div class="wrapper">
<h3>Create an automated numbering system</h3>
<div class="tags"><span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>parent {
counter-increment: elements;
}
element:before {
content: counter(elements);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Although it won't work in legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr>, this <abbr title="Cascading Style Sheets">CSS</abbr> snippet can be useful for numbered lines of code, headings, poetry, etc.</p>
<p class="details-para">Make sure to disable selection in some cases; nobody wants to copy-paste code with numbers breaking it.</p>
<p class="details-para"><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters">Check this <abbr title="Mozilla Developer Network">MDN</abbr> tutorial</a> for further details.</p>
</div>
</div>
</section>
<section class="trick" id="layout-grid">
<div class="wrapper">
<h3>Build a super simple responsive grid</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@supports (display: -webkit-flex) or (display: flex) {
ul.grid,
ol.grid {
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-flex: 1 1 15em;
flex: 1 1 15em;
}
ul.grid li,
ol.grid li {
page-break-inside: avoid;
break-inside: avoid;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">What if you could make the most of the page’s width for, say, an inline table of contents or a list of ingredients?</p>
<p class="details-para">By using flexbox, you can create a responsive grid which should behave according to a preferred width (the third value in <code>flex</code> e.g. <code>15em</code>).</p>
<p class="details-para">Of course you may want to provide a fallback for Reading Systems which don't support flexbox.</p>
</div>
</div>
</section>
<section class="trick" id="layout-valign">
<div class="wrapper">
<h3>Vertically-align elements on a page</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@supports (display: -webkit-flex) or (display: flex) {
parent {
min-height: 95vh;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-justify-content: {value};
justify-content: {value};
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Pages of an eBook don’t have a middle or a bottom, right? With flexbox, they now do.</p>
<p class="details-para">Make sure to use the <code>min-height</code> property so that the container’s height can grow in case the user sets a huge <code>font-size</code>… or else contents will collapse.</p>
<p class="details-para">If you’re not familiar with flex properties and values, check <a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">CSS-Tricks’ complete guide to flexbox</a>.</p>
<p class="details-para">Finally, you should provide a fallback for Reading Systems which don't support flexbox.</p>
</div>
</div>
</section>
<section class="trick" id="layout-wrap">
<div class="wrapper">
<h3>Give text wraps a modern twist</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>element {
float: left;
}
@supports (-webkit-shape-outside: {value}) or (shape-outside: {value}) {
element {
-webkit-shape-outside: {value};
shape-outside: {value};
-webkit-clip-path: {value};
clip-path: {value};
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">For decades, text has wrapped around the floated element’s bouding box, which means it couldn’t wrap the object like it does in <abbr title="Desktop Publishing">DTP</abbr> software.</p>
<p class="details-para">By using <code>shape-outside</code> and <code>clip-path</code>, you can define a shape around which the text should wrap.</p>
<p class="details-para">And there’s even a <a href="https://chrome.google.com/webstore/detail/css-shapes-editor/nenndldnbcncjmeacmnondmkkfedmgmp">Chrome extension to help you do that</a>.</p>
</div>
</div>
</section>
</section>
<section class="category" id="images">
<h2>Images</h2>
<section class="trick" id="images-ratio">
<div class="wrapper">
<h3>Force images to keep their aspect ratio</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>img {
object-fit: contain;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">When sizing images based on <code>width</code> or <code>height</code>, you’ll probably end with distorted images in some contexts. It turns out <a title="MDN — object-fit" href="https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit">there is a <abbr title="Cascading Style Sheets">CSS</abbr> property to manage that</a>.</p>
<p class="details-para">Get used to add <code>object-fit:contain</code> to <code>img</code> as this property prevent this distortion.</p>
</div>
</div>
</section>
<section class="trick" id="images-caption">
<div class="wrapper">
<h3>Keep an image with its caption</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>figure {
page-break-inside: avoid;
break-inside: avoid;
}
@supports not ((page-break-inside: avoid) and (break-inside: avoid)) {
figure {
-webkit-column-break-inside: avoid;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Readability is as important as legibility and this is why you should take care of the relationship between elements.</p>
<p class="details-para">For best comprehension, the image and its caption should be displayed on the same page so let’s avoid a page-break inside figures.</p>
</div>
</div>
</section>
<section class="trick" id="images-reflow">
<div class="wrapper">
<h3>Make an image responsive to its caption’s font-size</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@supports (height: calc(98vh - 5em)) {
img {
width: auto;
max-width: 100%;
min-height: 300px;
height: calc(98vh - 5em);
max-height: 95%;
object-fit: contain;
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">For images with a portrait aspect ratio, you must go the extra mile so that the image and (part of) its caption are displayed on the same page.</p>
<p class="details-para">This is where the <abbr title="Cascading Style Sheets">CSS</abbr> <code>calc()</code> function really shines. It allows you to dynamically compute the height of an image depending on the current <code>font-size</code>.</p>
<p class="details-para">In this example, the image’s height should ideally be 98% of the page minus 3 lines of text (with a <code>line-height</code> of <code>1.5</code>). Finally, <code>min-</code> and <code>max-height</code> provide a range for the image sizing.</p>
</div>
</div>
</section>
</section>
<section class="category" id="misc">
<h2>Misc.</h2>
<section class="trick" id="misc-currentColor">
<div class="wrapper">
<h3>Use text color as a variable</h3>
<div class="tags"><span class="tag">ePub2</span> <span class="tag">EPUB3</span> <span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>element {
border: 1px solid currentColor;
}
svg {
fill: currentColor;
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If you want borders, backgrounds or <abbr title="Scalable Vector Graphics">SVG</abbr>’s fill to be the same color as text, including in night modes, <code>currentColor</code> is your best bet.</p>
<p class="details-para">Indeed, <code>currentColor</code> sort of behaves like a variable: <a href="https://css-tricks.com/currentcolor/">it inherits the current color of text</a>.</p>
<p class="details-para">In other words, when Reading Systems set a light color for text in night mode, <code>currentColor</code> will become this color.</p>
</div>
</div>
</section>
<section class="trick" id="misc-epubtype">
<div class="wrapper">
<h3>Style epub:type</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@namespace epub "http://www.idpf.org/2007/ops";
[epub|type~="toc"] {
/* styles */
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Problem with <code>epub:type</code> is that you have to escape the colon in <abbr title="Cascading Style Sheets">CSS</abbr>…</p>
<p class="details-para">Unless you declare a namespace at the top of your style sheet. You can now use <code>epub|style</code> instead of <code>epub\:style</code>, which is a lot more readable and maintainable.</p>
</div>
</div>
</section>
<section class="trick" id="misc-supports">
<div class="wrapper">
<h3>Prevent unsupported styles from impacting legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr></h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@supports ({property}: {value}) {
element {
{property}: {value};
}
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If you want to do <a title="Progressive enhancements make books progressive" href="http://www.booknetcanada.ca/blog/2016/12/12/progressive-enhancements-make-books-progressive">progressive enhancement</a> and don't want to risk your stylesheet being entierely ignored in legacy RMSDK, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@supports">feature queries</a> are the way to go.</p>
<p class="details-para">Besides asking Reading Systems if they support a <abbr title="Cascading Style Sheets">CSS</abbr> declaration, it will basically protect the nested styles from being parsed by the legacy RMSDK. It can be pretty useful with the CSS <code>calc()</code> function for instance.</p>
<p class="details-para">And <code>@supports</code> can protect media queries too.</p>
<p class="details-para">The only downside is that Internet Explorer 11 doesn't support feature queries and Adobe Digital Editions 4.5 is using its rendering engine (Trident) on Windows. As a consequence, those styles won't be applied even though Internet Explorer supports them.</p>
</div>
</div>
</section>
<section class="trick" id="misc-kindle">
<div class="wrapper">
<h3>Declare specific styles for Kindle</h3>
<div class="tags"><span class="tag">Kindle</span></div>
<div class="code-snippet">
<pre><code>@media amzn-kf8 {
/* Specific KF8 styles (new format) */
}
@media amzn-mobi {
/* Specific Mobi7 styles (old format) */
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">If for some reason you must add or override styles for Kindle, those two media queries can help. KindleGen will indeed take them into account when converting your <abbr title="Electronic Publication">EPUB</abbr> file.</p>
<p class="details-para"><strong>Do not ever let them empty in your EPUB file</strong> since that would crash the legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr> and all the Reading Systems using it.</p>
</div>
</div>
</section>
<section class="trick" id="misc-monochrome">
<div class="wrapper">
<h3>Style for monochrome</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@media (monochrome) {
/* Styles */
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Although this media query won't work with eInk devices, it can help solve accessibility issues.</p>
<p class="details-para">MacOS and iOS indeed ship with a monochrome switch in system preferences (accessibility panel) which, when enabled, will trigger the <code>monochrome</code> media.</p>
<p class="details-para">In other words, you could adapt colors to improve contrast for this mode.</p>
<p class="details-para">Make sure to protect this media query from legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr>’s parsing because your entire stylesheet could be ignored or, even worse, crash some apps and devices.</p>
</div>
</div>
</section>
<section class="trick" id="misc-pointer">
<div class="wrapper">
<h3>Style for touch or click input</h3>
<div class="tags"><span class="tag">EPUB3</span></div>
<div class="code-snippet">
<pre><code>@media (pointer: coarse) {
/* Styles for touch input */
}
@media (pointer: fine) {
/* Styles for mouse input */
}
</code></pre>
</div>
<h4 class="summary">Details</h4>
<div class="details">
<p class="details-para">Footnote references styled as in print (superscript) might provide users with a mediocre experience on touch devices. Fortunately, there is a media for such a case.</p>
<p class="details-para">The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer"><code>pointer</code> media</a> returns the accuracy of the primary input mechanism of the device, which means touch will return <code>coarse</code> while mouse will return <code>fine</code> for instance.</p>
<p class="details-para">In other words, you could increase the size of clickable elements for <code>coarse</code>.</p>
<p class="details-para">Make sure to protect this media query from legacy <abbr title="Adobe Reader Mobile Software Development Kit">RMSDK</abbr>’s parsing because your entire stylesheet could be ignored or, even worse, crash some apps and devices.</p>
</div>
</div>
</section>
</section>
</main>
<footer>
<p class="secondary">Version 1.0.1<br/></p>
<p class="secondary"><a href="https://github.com/FriendsOfEpub/eBookTricks/blob/master/LICENSE">LGPLv3 Licence</a> | <a href="https://github.com/FriendsOfEpub/eBookTricks">Source</a></p>
<p class="secondary">This tool is part of the <a href="https://github.com/FriendsOfEpub/Blitz">Blitz eBook Framework</a></p>
</footer>
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript">
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/eBookTricks/sw.js', {scope: '/eBookTricks/'})
}
</script>
</body>
</html>