Skip to content

Instantly share code, notes, and snippets.

@philschatz
Last active December 31, 2015 11:58
Show Gist options
  • Save philschatz/7982740 to your computer and use it in GitHub Desktop.
Save philschatz/7982740 to your computer and use it in GitHub Desktop.
HTML and CSS

Reasons for HTML & CSS+

Background

It would be easy if:

  • a piece of content is in exactly 1 book (overriding titles, collection context matters)
  • links would point to places within the current doc
  • could layout each page individually (PDF page breaks)

Actors:

Stacey cares about:

  • page breaks (extra
    tags cause problems)
  • linking to other parts of the book
  • global numbering ("Exercise 4.23" instead of "Exercise 3")
  • different styles for diff books (banner images, borders, moving content and renumbering)

Dak cares about:

  • giving "good-enough" styling on the web
  • some numbering, some style

Michael cares about:

  • Having a canonical format (writing XSLT)

Things to keep in Mind

  • we decided on having a "rich" web app (capable of doing Javascript)
  • feature headings in different books
  • numbering (whole-book and chinked)
  • collating content (glossary/exercises)
  • page-breaking (for PDF)
  • attributes in the right spot for styling
  • There are 20 OSC books
  • There are 4 output formats: Online, PDF, EPUB, Mobi (html-)

The Numbers

If each output format is tweaked slightly differently then:

  • There will need to be a script for each output format (XSLT, javascript, or python) that converts from the canonical format.
  • There will need to be a separate CSS file for each output format for each book style.

So, 4 conversion scripts and 4*20 CSS files. That's at least 84 different files to keep in sync. Any change requires testing either, 4 (only 1 book changed; test all the outputs), 20 (one output format changed; test all the books), or 80 books (each book is several hundred pages long).

Examples

  • Numbering Exercises (important for assigning HW to students)
  • CALS tables (data attributes need to "trickle up" for CSS styling)
  • Injected
    causes problems for page-breaks
  • Statistics "Try It" (uses display: run-in)
  • Moving content
  • Footnotes
  • links to other pieces of content (target-text) and overriding titles
  • Single page vs multiple pages (PDF vs EPUB/web)

Custom Note ("Feature") Styling

One of the most visible ways the books differ are by banner images above notes. Every book has a different set of banner images. This requires a CSS file for every PDF and a CSS file for every webview.

CALS Tables

Styling complex tables requires (among other things) "peeking" into the element and looking up styling attributes:

table:has(.entrytbl) { /*do not stripe*/ }
// Set the width of a column
colgroup > col[data-colwidth] { width: attr(data-colwidth); }

Injected <section> and Statistics "Try It" (uses display: run-in)

Adding a <section> around a very large Exercise causes the whole exercise to break on the title, instead of inside the content. So, this would need to either not be done or be done differently for webview and PDF/ePUB.

Also, the "Try It" notes in the Statistics book use display: run-in; to put the number (and calculator image) on the same line as the rest of the text.

Webkit is the only browser that partially supports it, and still would not work if titles were wrapped in a <heading>.

The CSS would look like the following:

.note.try-it > .title { display: run-in; }

Labeling Notes/Exercises

The [data-label] attribute describes how a Note/Figure/Table/... is labeled. It can suppress a label, or force a different label. Also, it affects how the Note/Figure/Table counters are incremented. This was a stop-gap for not allowing people to provide their own CSS and I believe it should be deprecated. IMPORTANT: Also, remember the pesky : that only exists if [data-label!=''] and there is a child .title!

Lists

Contains many attributes that affect how a list is displayed. This was a stop-gap for not allowing people to provide their own CSS and I believe it should be deprecated. Some attributes that cannot be expressed in CSS (and how they can be in CSS+):

// [data-mark-prefix] and [data-mark-suffix]
ul[data-mark-prefix] > li::before::before { content: parent(attr(data-mark-prefix)); }
ul[data-mark-sufix]  > li::before::after  { content: parent(attr(data-mark-suffix)); }

// [data-item-label]  (custom bullet character)
ul[data-item-label] > li::before { content: parent(attr(data-item-label)); }

// [data-item-sep]
ul[data-item-sep] > li::after { content: parent(attr(data-item-sep)); }

Moving Content

Exercises and glossary terms are moved around and numbered based on where they are moved to. Moving them is currently done with XSLT for PDF and numbering them is done with CSS.

These should also probably move to the bottom of the page in Webview in areas corresponding to the areas they move to in the PDF ("Conceptual Questions", "Homework Problems", etc).

This can be done in CSS+ by writing:

.exercise.homework { move-to: homework-bucket; }

.page::after::before { content: 'Homework Problems';
.page::after         { content: pending(homework-bucket); }

Footnotes

In Webview, footnotes should appear at the bottom of the page with a link to the footnote and a link back to the content (see wikipedia). This can be expressed in CSS+. See http://philschatz.github.io/css-polyfills for the example. In PDF footnotes are already collated at the bottom of the page by PrinceXML (using the W3C GCPM Draft)

Links to other pieces of content

Given a link to a Figure in another module we would like the link text to be the following:

// link:              <a href="m123#id456">[link]</a>
// Expected Webview:  <a href="m123#id456">Figure 3 on another page</a>
// Expected PDF/EPUB: <a href="m123#id456">Figure 4.7</a>

If we were consistent and Labels were always inserted as &::before {} then link text can be described easily:

// Example Webview  CSS+: 
a[href] { content: target-text(attr(href), content(before)) ' on another page'; }
// Example PDF/EPUB CSS+: 
a[href] { content: target-text(attr(href), content(before)); }

To support something like a link to a Section in another Module we could make it be Section 4.7: Title Here instead of just 4.7 by doing the following. This would involve 1. checking if the link is to a section, and 2. getting the Section title. This assumes:

  • Labels are inserted as &::before{}
  • If a section has a title and a label then the .title::before gets a :

Then, the CSS+ could look like the following:

a[href] { 
  content: x-target-is(attr(href), '.section') // Guard to make sure this rule only applies to targets that are a section
           'Section ' 
           target-text(attr(href), content(before)) 
           target-text(attr(href), content('> .title'));
  }

Advanced links (Phil's Notes)

If you do not want to rely on the label being inside ::before then you can use the x-target-is() guard an look up the counters. Note: you will still need to look up the title as before (and add a colon)

// x-target-is(id, selector1)
//   looks up an element and if the selector is matched, returns the corresponding value; otherwise does not resolve
//   This way you can have several stacked up:

a[href] { 
  // Rule to style a Link to a Note (does not care if it is in a chapter/appendix)
  content: x-target-is(attr(href), '.note') 
           'Note '
           target-counter(attr(href), note);

  // Note: the chapter counter. To make it work with Preface/Appendix notes we need to add some more:
  content: x-target-is(attr(href), '.chapter .note')
           'Note '
           target-counter(attr(href), chapter) '.'
           target-counter(attr(href), note);

  content: x-target-is(attr(href), '.appendix .note')
           'Note '
           target-counter(attr(href), appendix, upper-alpha)
           target-counter(attr(href), note);
}

Proposal

  1. Use one language to perform the transforms
  2. Use JavaScript instead of XSLT/Python
  3. Separate out Slots (CSS Rules) and Skeleton (CSS Selectors) files
  4. Use one HTML structure
  5. Use one CSS file
  6. Use css-polyfills to fill in the gaps

Why Use 1 Language

This way all the extra "injected HTML" is done by one library (maintenance and testing).

Why Javascript instead of XSLT/Python for conversion

  1. XSLT is "hard" to learn/maintain (Michael)
  2. Python requires round-tripping (think authoring and rich web app; needs to round-trip on every save)

Example: Overriding section titles requires having multiple copies of a Module HTML file for webview (the links would be different)

Why Slots and Skeletons

  1. Removes dependence on Docbook, webview, Single HTML (PDF), or chunked HTML (EPUB). The "Skeleton" file handles that
  2. Makes adding new books easier since you only need to style "logical" pieces of books
  3. Can hide "ugly" things like [data-label] rules (dak), numbering logic (stacey), etc

Why Shared HTML Structure

  1. Developers/Designers only need to know 1 HTML format
  2. ReImporting an EPUB is simple
  3. Can use the same CSS (slots at least)

Why Shared CSS

  1. Book-specific styling shows up instantly on all output formats (colors, banners, etc)
  2. only 20 CSS files instead of 4*20 (plus, most of them extend each other)

Why css-polyfills

  1. EPUB readers support a subset of CSS2 (no pseudoselectors)
  2. PrinceXML supports things like target-counter/target-text for links)
  3. Webview needs to style links to other modules (target-counter/target-text)
  4. The canonical HTML does not have enough "hooks" for plain CSS (labels, numbering, CALS Tables)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment