Movatterモバイル変換


[0]ホーム

URL:


CSS Polyfills

Describe more using CSS!

Use CSS to describe menial tasks in JavaScript likewrapping elements for styling,moving content around,numbering things,clickable footnotes, and more!

Learn More GitHub

What if you could use CSS to do more?

// Use jQuery selector Extensions.example:has(>.title) { border: 1px dotted; }.example:lt(3)        { background-color: red; }// Wrap Elements just for styling purposes.example:outside        { border: 1px solid red; }.example:outside:before { content: 'Example: '; }// Floating, clickable Footnotes.footnote:footnote-call { x-tag-name: 'a'; }// Advanced Attribute Lookup.note[title] > .title { content: x-parent(attr(title)); }// Number links to other elementsa[href] {  content: 'See Chap ' target-counter(attr(href), chapter)                  ': ' target-text(attr(href), content());}// Customize Link text based on what the link target isa[href] {  content: x-target-is(attr(href), 'table') 'See Table';  content: x-target-is(attr(href), '.note') 'See Note';}// Move content in the DOM.definition    { move-to: glossary-bucket; }.glossary-area { content: pending(glossary-bucket); }// Set a string ... and then use ith1 { string-set: chapter-title content(); }.chap-end { content: '[End of ' string(chapter-title) ']'; }
run unit tests/coverage

Motivation

CSS is constantly changing and there is a lack of tools for experimenting with new ways of using it.

There are some great Working Drafts that describe extensions to CSS (Generated Content for Paged Media andCSS3 Generated and Replaced Content Module), features often implemented using ad-hoc JavaScript.

Below are some interactive examples showing how powerful CSS can be at describing these common operations.

For a full list of CSS selectors, rules, and functions see the GitHub README

Sections


How to Use in a Browser

Running in a browser is the easiest way to get started and good for testing out the CSS.

Include the stylesheet with therel set to"stylesheet/css-polyfills":

<link rel="stylesheet/css-polyfills"      type="text/css"      href="styles.css" />

Then use thedcss-polyfills.js built in the/dist/ directory, and include it in your page, like so:

<script src="dist/css-polyfills.js"></script>

Seeexamples/browser.html for an example.

Moving Content

Moving content in the DOM is simple using themove-to: bucket-name; andcontent: pending(bucket-name); rules defined inCSS3 Generated and Replaced Content Module.

// This element will be moved into the glossary-bucket....def-a { move-to: bucket-a; }.def-b { move-to: bucket-b; }// ... and dumped out into this area in the order added..area-a { content: pending(bucket-a); }.area-b { content: pending(bucket-b); }// Also, styling occurs **before** elements are moved so ....before div { background-color: lightgreen; }
<div> <div>This will be in the 1st Area A</div> <div>This will be in Area B</div> <div>This will also be in the 1st Area A</div></div><h3>Area A</h3><div></div><h3>Area B</h3><div></div><div>This will be in the 2nd Area A</div><h3>Area A</h3><div></div>

Looking up Cross-referenced text and counters

Looking up text inside some other element is simple using thecontent: target-text(attr(href)); andcontent: target-counter(attr(href), chapter-coutner); rules defined inCSS Generated Content for Paged Media Module.

// Just set a counter so we can look it up laterh3 { counter-increment: chap; }h3:before { content: 'Ch ' counter(chap) ': '; }// Look up the text on the target.xref {  content: 'See ' target-text(attr(href), content(contents));}// Look up the counter on the target.xref-counter {  content: 'See Chapter ' target-counter(attr(href), chap);}
<h3>The Appendicular Skeleton</h3><p>Here is a reference to another chapter: <a href="#ch2">Link</a></p><h3>The Brain and Cranial Nerves</h3><p>Here is a reference to another chapter: <a href="#ch1">Link</a></p><p>A reference using target-counter: <a href="#ch1">Link</a></p>

Making HTML elements in CSS

It may be useful to add elements into the HTML (for styling). CSS2 has the:before and:after selectors for this reason.

TheCSS3 Content Module is like:before on steroids! You can nest the pseudo selectors to add and style arbitrarily large elements. It also introduces the:outside pseudoselector which wraps an element and adds additional styling.

The example below builds on the previous example of using counters andtarget-text to allow styling individual parts of the injected "Ch #: " text.

h3:before { content: 'Ch ' counter(chap) ': '; }// The previous rule is valid CSS2 and creates the following DOM:// [ [Ch 2:] Chapter Title]// Note: There are only 2 elements we can styleh3                { counter-increment: chap; }h3:before:before  { content: '[Ch ]'; }h3:before         { content: '[' counter(chap) ']'; }h3:before:after   { content: '[: ]'; }h3:outside:before { content: '(chapter starts here)'; }// Instead, the previous styles create the following// (providing 7 elements that can be styled):// [//   [Chapter starts here]//   [//     [ [Ch] [2] [: ] ]//     Chapter Title//   ]// ]
<h3>The Appendicular Skeleton</h3><p>Lorem ipsum lorem ipsum.</p><p>Lorem ipsum lorem ipsum.</p><h3>The Brain and Cranial Nerves</h3><p>Lorem ipsum lorem ipsum.</p><p>Lorem ipsum lorem ipsum.</p>

Setting Strings

Sometimes it is useful to set a string and then use it later. An example would be having the current chapter on each page of a book.

FortunatelyCSS Generated Content for Paged Media defines thestring-set: string-name value; andcontent: string(string-name); rules.

An example is shown below:

// Set a string somewhere...h3 { string-set: chapter-title content(); }// ... And then use it!.chap-end { content: '[End of ' string(chapter-title) ']'; }
<h3>The Appendicular Skeleton</h3><p>Here is some content for the chapter.</p><div></div><h3>The Brain and Cranial Nerves</h3><p>Here is some content for another chapter.</p><div></div>

Customizing Link Text

Sometimes it is useful to change the text of a link based on what it points to. For example, a link to a figure may say "see Figure 4.3" and a link to another chapter might say "See Section 7.2: Trapezoids".

Changing the text of a link can be accomplished usingx-target-is(id, '.title') which works like a switch statement in many programming languages.

An example is shown below:

a[href] {  // Use x-target-is as a switch for which link text to use  content: x-target-is(attr(href), 'figure') 'See Figure';  // Link to a section WITHOUT a title  content: x-target-is(attr(href), 'section:not(:has(>.title))')           'See ' target-text(attr(href), content(before));  // Link to a section **with** a title  content: x-target-is(attr(href), 'section:has(>.title)')           'See ' target-text(attr(href), content(before))           target-text(attr(href), content('> .title'));}// Some uninteresting formatting just for the demosection { counter-increment: section; }section::before { content: counter(section) ' '; }
<figure><i></i> image</figure><a href="#id-figure">LINK</a><hr/><section>Section without a title</section><section> <strong>Kinematics</strong> Section with a title</section><a href="#id-section">LINK</a><br/><a href="#id-section-title">LINK</a>

Putting it Together: Footnotes (Clickable and Floating)

Footnotes that move to the bottom of a page and leave a little numbered link are described inGenerated Content for Paged Media: Footnotes

They can be implemented using the pseudoselector:footnote-call and the extension rulesx-tag-name:,x-attr:, andx-ensure-id:.

Here is an example implementation of footnotes.

.footnote {  // Ensure the footnote has an `id` (so we can link to it)  x-ensure-id: 'id';  // Move it to the next `footnote-area` (page end)  move-to: footnote-area;  counter-increment: footnote;  display: block; // Plain CSS, nothing interesting}// The content that is left behind after the move-to.footnote:footnote-call {  // Make the stub that is left behind a link...  x-tag-name: 'a';  // ... whose href points to the footnote.  x-attr: href '#' attr(id);  content: '[###]';  content: '[' target-counter(attr(href), footnote) ']';}//.footnote:footnote-marker,.footnote:before {  content: counter(footnote) ': ';}// Area where the footnotes will be collected.footnotes-area {  content: pending(footnote-area);  //counter-reset: footnote;}
<p>Text with a <span>FOOTNOTE!</span>.</p><p>More paragraphs with <span>footnote text</span> <span>another footnote</span>.</p><hr/><h3>Footnotes Area (bottom of the page/chapter)</h3><div></div>

Sizzle Selector Extensions

Sizzle has several usefulextensions to CSS selectors that allow us to target elements better. Now, you can use them directly in CSS files!

Some examples include::has() for looking inside an element and:lt() for matching elements less than a specific index.

Try using them with the demo below!

.example:has(>.title) {  background-color: pink;}.count:lt(3) {  background-color: lightblue;}
<div>Does not have title</div><div><div>Has title</div></div><hr/><div>First</div><div>Second</div><div>Third</div><div>Fourth</div>

Adding Extensions

Continuing with the Move example, it may be nice to sort the elements being moved like in a glossary.

Adding these extensions is pretty straightforward. Here is the definition ofx-sort(bucket).

'x-sort': (env, pendingElsNode) ->  pendingEls = pendingElsNode.value  sorted = pendingEls.sort (a, b) ->    a = a.text()    b = b.text()    return -1 if (a < b)    return 1  return sorted

You can use it in a demo below. Note that the items are sorted alphabetically.

// This element will be moved into the glossary-bucket....def {  move-to: glossary-bucket;}// ... and dumped out into this area in the order added..glossary-area {  content: x-sort(pending(glossary-bucket));}
<div> (C)ut hair</div><div> (A)waken self</div><div> (B)rush teeth</div><h1>Glossary</h1><div></div>

[8]ページ先頭

©2009-2025 Movatter.jp