A semantically-consistent pure CSS slide renderer
Take Five! is a slide renderer written in pure CSS and oriented to the semantics of HTML (semantic nodes, microdata, microformats, RDFa). It can be used as a simple lightbox for images and videos, or as a complete slide viewer for complex contents. Before further reading, please visit the live demo.
In order to create a slide with Take Five! all you need to do is to include takefive(.min).css
in your document, then use one of the following basic syntaxes:
<p><a href="#my-hashtag">My slide</a></p> <article id="my-hashtag" class="slide"> <element-to-be-slided /> </article>
<p><a href="#my-hashtag">My slide</a></p> <article id="my-hashtag" class="slide"> <nav> <a href="#nowhere" rel="parent"></a> </nav> <element-to-be-slided /> </article>
<p><a href="#my-hashtag">My slide</a></p> <article id="my-hashtag" class="slide"> <element-to-be-slided /> <nav> <a href="#nowhere" rel="parent">My diary</a> </nav> </article>
<p><a href="#my-hashtag-5">My slide</a></p> <article id="my-hashtag-5" class="slide"> <header> <h2>[title]</h2> </header> <nav> <a href="#nowhere" rel="parent">My home page</a> <a href="#my-hashtag-4" rel="prev">[previous slide name]</a> <a href="#my-hashtag-6" rel="next">[next slide name]</a> <a href="#my-hashtag-1" rel="first">[first slide name]</a> <a href="#my-hashtag-9" rel="last">[last slide name]</a> Etc. etc. </nav> <this-element-will-be-slided /> <this-element-will-be-displayed-on-the-right-side-of-the-screen /> <this-element-will-be-displayed-on-the-right-side-of-the-screen /> <etc. /> <footer>[footer]</footer> <aside>[aside]</aside> </article>
Etc. etc.
If you want Take Five! to behave responsively on small screens, add
<meta name="viewport" content="width=device-width, initial-scale=1.0">
to the <head>
of your page. For more advanced tweaks, such as touch and keyboard events and cleaning the browser history, see the § Plugins and § FAQ sections below or visit the JavaScript Add-Ons page.
The following minimalistic code
<p style="text-align: center; font-size: 2em;"> <a href="#photo-of-the-day">Photo of the day</a> </p> <article class="slide" id="photo-of-the-day"> <figure> <img src="media/1.jpg" alt="Photo of the day" /> <figcaption>Photo of the day</figcaption> </figure> <nav> <a href="#nowhere" rel="parent">My diary</a> </nav> </article>
will produce this result.
The philosophy of Take Five! is that of facilitating a general semantics for expressing a slide with HTML (independently of how this is rendered), rather than focusing on means to express a layout.
In the original meaning of the term a slide is a single page projected on a wall through a beamer or a lightbox. The term does not describe weather a slide is blue or red, or whether it contains a picture or text, but only that its content must fit in a single page and the lights in the room are usually switched off.
A slide can also be taken in the hands and read in its physical form with the lights on, thus the most characterizing aspect of a slide is actually its conciseness and independence, not how it is displayed.
With its inception HTML5 introduced six semantic elements (<article>
, <aside>
, <footer>
, <header>
, <nav>
and <section>
), one of which is well suited to represent self-contained compositions: the <article>
element.
The <article>
element represents a complete, or self-contained, composition in a document, page, application, or site. This could be a magazine, newspaper, technical or scholarly article, an essay or report, a blog or other social media post.
For non-semantic properties, HTML possesses also a class
attribute, which although cannot describe what things are, can still be used to describe how things look. For describing an <article>
that is projected on a wall it is then possible to write <article class="slide">
.
Since a class
attribute does not express semantics, such a slide remains primarily an <article>
element, and <article class="slide">
translates as “<article>
that looks like a slide” (but not as “<article>
that represents a slide”).
Take Five! is a slide renderer written in CSS, which means that it can only decide how things look, not what they are. However, in deciding what to give a style to, Take Five! focuses on elements that have a meaning (semantic elements), instead of generic elements that simply claim a layout (as it would be, for instance <div class="i-want-a-layout"> ... </div>
).
Concretely speaking this has two effects:
class
attribute is not used to identify further elements besides the <article class="slide">
container: the elements' intrinsic semantics (i.e., their tag names) is already sufficientclass
attribute is used only for expressing layout optionsA densely populated slide (<article>
), besides its main content, can possess a title, a footer and some other information aside; therefore when this happens Take Five! gives a style to the <header>
, <footer>
and <aside>
elements nested within it. In an internet context a slide can also be linked to other slides, hence Take Five! gives a layout to the <nav>
element as well. A <nav>
element however does not make much sense in a printed page, so when the slide is “taken in the hands” (printed) the <nav>
element is not displayed.
Elements are not the only things that can express semantics in HTML. A further place that conveys semantics is the rel
attribute assigned to links. Therefore, when a slide is displayed on a screen and the <nav>
element is shown, Take Five! relies on the rel
attributes for deciding how to style each link and what role it has in the viewport.
Each slide (<article id="my-hashtag" class="slide"> ... </article>
)
id
attribute)"slide"
class (but a few additional classes are available for special options)Several slides belonging to a single gallery can be logically packed together within any parent element – normally a <section>
element is chosen for it.
The way this CSS operates is quite simple: the first direct child of the <article class="slide">
element found to be neither a <header>
, nor a <nav>
, nor a <footer>
, nor an <aside>
will be placed at the center of the viewport (from now on, this will be called “the fifth element” or “the <leeloo>
element”, after Luc Besson's movie). Further direct children that match the previous condition, if present, will be displayed on the right side of the screen, in their normal order.
On large screens, when present, the <header>
, <nav>
, <footer>
and <aside>
elements are positioned to fill the entire space of the viewport.
On small screens everything is aligned in one scrollable single column, where only the <header>
, if present, is always positioned on top of the slide, while all other elements follow their natural disposition assigned via HTML
It is possible to test the order of the elements by visiting the Schematic page.
Sub-children of the viewport are displayed normally, in their natural order and without any style applied beyond basic layout. The only exception is made for links that are children of the main <nav>
, which are considered as internal navigation links and styled according to their rel
attribute (here the list of the supported keywords).
Galleries can be nested within other galleries, possibly relying on <section>
elements. A link to the child gallery is usually given by an anchor with the "child"
keyword assigned to its rel
attribute.
<p style="text-align: center; font-size: 2em;"> <a href="#slide-1">Nested galleries</a> </p> <section> <article id="slide-1" class="slide"> <element-to-be-slided /> <nav> <a href="#slide-1-1" rel="child">Nested gallery</a> <a href="#nowhere" rel="parent">My diary</a> </nav> </article> <section> <article id="slide-1-1" class="slide"> <element-to-be-slided /> <nav> <a href="#slide-1" rel="parent">Item #1</a> </nav> </article> </section> </section>
A more articulated example is available here. For more information on how to create a gallery tree it is possible to follow this tutorial.
Take Five! relies only on one single class: the "slide"
class applied to an <article>
element. Further classes are available for optional features, although none of them is structurally required. The complete list of available classes is shown below.
<article>
element (i.e., the slide)Class | Declared as | Meaning |
---|---|---|
"slide" |
article.slide |
Declares an <article> element as a slide |
"verbose" |
article.slide.verbose |
When a slide is declared with the "verbose" class a label will be added by default to all the links nested inside the main <nav> . Without "verbose" only a[rel="parent"] is displayed with a label. |
"foyer" |
article.slide.foyer |
When a slide is declared with the "foyer" class links with a known rel attribute nested inside the main <nav> will appear in the left menu together with links with an unknown rel attribute. Known rel attributes are "parent" , "next" , "prev" , "first" , "last" , "index" , "attachment" , "bookmark" , "author" , "discussion" , "tag" and "child" . The "tag" and "child" keywords always place the links they generate in the menu. |
"wrap" |
article.slide.wrap |
A transparent layer will cover the entire slide. As scrolling will become inaccessible, there should be no scrollable content when a slide is declared as "wrap" . |
"pinned" |
article.slide.pinned |
A slide declared with the "pinned" class will not generate a clickable background layer to exit (see example). |
"no-hashtag" |
article.slide.no-hashtag |
It is possible to prevent the hashtag from being displayed on the bottom-right corner of the viewport by using the "no-hashtag" class – as in <article class="slide no-hashtag" id="my-hashtag"> ... </article> . |
"nonadaptive" |
article.slide.nonadaptive |
Automatic adjustments for small screens or particular devices will be disabled if the "nonadaptive" class is present. Slides will look alike on every screen. |
All the classes above can form compound class names, as in <article class="verbose foyer wrap pinned nonadaptive no-hashtag slide"> ... </article>
.
<nav>
Class | Declared as | Meaning | Domain |
---|---|---|---|
"with-label" |
article.slide > nav:first-of-type a[href].with-label |
Links declared with the "with-label" class will be accompanied by a label. |
verbosity |
"no-label" |
article.slide > nav:first-of-type a[href].no-label |
Links declared with the "no-label" class will not be accompanied by a label. |
|
"tab" |
article.slide > nav:first-of-type a[href].tab |
Links declared with the "tab" class will appear in the <nav> menu as tabs. |
appearance |
"plate" |
article.slide > nav:first-of-type a[href].plate |
Links declared with the "plate" class will appear in the <nav> menu as plates. By default only a[rel="child"] is styled as such. |
|
"vision" |
article.slide > nav:first-of-type a[href].vision |
Links declared with the "vision" class will not appear in the <nav> menu at all, but as notifications on the top right corner of the viewport. This class is meaningful only for links that generate buttons via rel attribute. |
|
"no-rel" |
article.slide > nav:first-of-type a[href][rel].no-rel |
Links declared with the "no-rel" class will be treated as links with an unknown rel attribute (as in <a href="#sample-slide" rel="next" class="no-rel">Sample slide</a> or <a href="#sample-slide" rel="next" class="no-label no-rel">Sample slide</a>) . The rel attribute is still taken into account to generate a label if necessary. |
relation |
Classes belonging to the same domain are alternative to each other. Classes belonging to different domains can form compound class names, as in <a href="mailto:me@example.org" rel="author" class="plate with-label no-rel">John Doe</a>
.
Class | Declared as | Meaning | Domain |
---|---|---|---|
"z-low" |
article.slide . |
The "z-low" class assigns a low z-index to the element (lower than the background layer). Before applying this class to subchildren keep in mind that all direct children of the slide have a z-index already assigned; this needs to be canceled by applying the "z-none" class on the direct child. |
stacking context |
"z-mid" |
article.slide . |
The "z-mid" class assigns a middle z-index to the element (similar to that assigned by default to the <aside> and <footer> elements). Before applying this class to subchildren keep in mind that all direct children of the slide have a z-index already assigned; this needs to be canceled by applying the "z-none" class on the direct child. |
|
"z-high" |
article.slide . |
The "z-high" class assigns a high z-index to the element (above everything else). Before applying this class to subchildren keep in mind that all direct children of the slide have a z-index already assigned; this needs to be canceled by applying the "z-none" class on the direct child. |
|
"z-auto" |
article.slide .z-auto |
The "z-auto" class leaves the z-index property assigned by default by the CSS (if given). |
|
"z-none" |
article.slide . |
The "z-none" class reverts any z-index possibly assigned by the CSS. |
|
"clean" |
article.slide .clean |
The "clean" class removes borders and shadow from an element. |
decoration |
"roomy" |
article.slide .roomy |
The "roomy" class sets the following properties on big screens: max-height: 100%; overflow: auto; padding: 0 .5em 0 0; . On small screens these are transformed into: max-height: none; overflow: visible; padding: 0; . |
size |
Classes belonging to the same domain are alternative to each other. Classes belonging to different domains can form compound class names, as in <figure class="z-high roomy clean"> ... </figure>
.
data-*
attributesAttribute | Declared as | Meaning |
---|---|---|
data-context |
article.slide[data-context] |
The slide container (article.slide ) can optionally possess a data-context attribute, whose content will be displayed on the top left side of the viewport – as in <article class="slide" data-context="Hello world!" id="my-hashtag"> ... </article> (it takes 2.5 seconds to show up, so you must wait to see it). See also note below. |
data-label |
article.slide a[href][data-label] |
The data-label attribute can be used to create custom labels for individual links, or replace the default labels in the main <nav> 's links that possess a rel attribute. |
<article>
element; such element delimits a self-contained content, meaning that if all the other HTML except the <article>
are removed the content would still make sense to a reader. The function of the data-context
attribute is that of contextualizing the <article>
's content. It is confined to an attribute, so that the content of the <article>
remains still independent. It usually contains a small motto, a copyright notice or a mention of the hosting website. It should be used in complete freedom.This is the optional section of the framework. Some of these plugins could have been merged with the main CSS, but they have been kept separate to preserve modularity. Please feel free to bring new ideas.
takefive-counters.css
takefive-glyphs.css
takefive-i18n-*.css
takefive-maxsize.css
<leeeloo>
element when there are no visible links in the main <nav>
and no further content besides the <leeeloo>
element itselftakefive-polaroid.css
takefive-slides.css
<section>
elements with class "slides"
on screen, in order to display them only on the printed page.takefive-toolbar.css
<span>
/ <div>
elements, or openable <details>
elements, to be completed via JavaScriptIn addition to the CSS plugins above, you can have a look at the following JavaScript snippets, to be simply included in the document as such (please keep in mind that js-add-ons/takefive-clean-empty-hash.js
and js-add-ons/takefive-clean-history.js
are alternative to each other).
js-add-ons/takefive-keyboard-events.js
– for exiting a presentation via escape
keyjs-add-ons/takefive-touch-events.js
– for enabling touch eventsjs-add-ons/takefive-clean-history.js
– for clearing the history after leaving a presentationjs-add-ons/takefive-clean-empty-hash.js
– for cleaning the address bar from empty hash signs (#
)For a live example, please visit the JavaScript Add-Ons page.
"slide"
class applied to an <article>
element. Optionally the latter supports also the following six classes: "verbose"
, "foyer"
, "wrap"
, "pinned"
, "no-hashtag"
and "nonadaptive"
. Six optional classes are also available to navigation links: "with-label"
, "no-label"
, "tab"
, "plate"
, "vision"
and "no-rel"
.data-*
attributes does Take Five! support?data-*
attributes are supported: data-context
, optionally applied to the slide, and data-label
, optionally applied to links.<article class="slide">
element, to be displayed at the center of the screen (plain text direct child of the slide is always displayed on the right side of the screen). When present, the CSS takes also care of styling other children element of the main <article>
, but these are not required.<leeloo>
element: margin
, position
, left
, top
, box-sizing
, transform
, animation
and z-index
. No particular caution is required for <leeloo>
's children, so if you want to show fullscreen an element that relies on animations (i.e., it uses the animation
property), nest it inside a blank <div>
element or any other container of your choice.loading="lazy"
attribute on <img>
and <iframe>
elements.escape
key for exiting the slides?escape
key.
/* close the slide currently open or do nothing */ function closeCurrentSlide () { var oSlide = document.querySelector("article.slide:target"); if (oSlide) { var oExitLink = oSlide.querySelector("nav:first-of-type a[rel~=\"parent\"]"); location.assign(oExitLink ? oExitLink.href : "#"); } } window.addEventListener("keyup", function (oEvt) { if (oEvt.key === "Escape") { closeCurrentSlide(); } }, false);For a downloadable version, please see
js-add-ons/takefive-keyboard-events.js
.
(function() { var nDownX = null, nDownY = null; function handleTouchStart (oEvt) { const oFirstTouch = oEvt.touches[0]; nDownX = oFirstTouch.clientX; nDownY = oFirstTouch.clientY; }; function handleTouchMove (oEvt) { if (!nDownX || !nDownY) { return; } var oLink, sRel = null, nDiffX = nDownX - oEvt.touches[0].clientX, nDiffY = nDownY - oEvt.touches[0].clientY; switch (Math.abs(nDiffX) > Math.abs(nDiffY) ? nDiffX > 0 ? 3 : 2 : nDiffY > 0 ? 1 : 0) { /* Cases: `0` -> down swipe, `1` -> up swipe, `2` -> right swipe, `3` -> left swipe */ case 2: sRel = "prev"; break; /* Right swipe */ case 3: sRel = "next"; break; /* Left swipe */ } nDownX = null; nDownY = null; sRel && (oLink = this.querySelector("nav:first-of-type a[href][rel~=\"" + sRel + "\"]")) && location.assign(oLink.href); }; window.addEventListener("DOMContentLoaded", function () { const aSlides = document.querySelectorAll("article.slide"); for (var nIdx = 0, nLen = aSlides.length; nIdx < nLen; nIdx++) { aSlides[nIdx].addEventListener('touchstart', handleTouchStart, false); aSlides[nIdx].addEventListener('touchmove', handleTouchMove, false); } }, false); })();For a downloadable version, please see
js-add-ons/takefive-touch-events.js
.
history
!(function () { var bOpenedWithSlide = false, nHistCount = -1; function newSlideClicked () { nHistCount--; } function exitClicked (oEvt) { if (bOpenedWithSlide) { /* The page was loaded with a slide open */ bOpenedWithSlide = false; } else { history.go(nHistCount); oEvt.preventDefault(); } nHistCount = -1; } addEventListener("DOMContentLoaded", function () { var elIter, aLinks = document.querySelectorAll("article.slide a"), elTest = document.createElement("a"); bOpenedWithSlide = Boolean(document.querySelector("article.slide:target")); elTest.href = location.href; for (var nLen = aLinks.length, nIdx = 0; nIdx < nLen; nIdx++) { elIter = aLinks[nIdx]; elTest.hash = elIter.hash || "#"; if (elTest.href === elIter.href) { elIter.addEventListener("click", elIter.hash && document.querySelector("article.slide" + elIter.hash) ? newSlideClicked : exitClicked ); } } }, false); })();For a downloadable version, please see
js-add-ons/takefive-clean-history.js
.
js-add-ons/takefive-clean-empty-hash.js
.#
or #whatever
link for exiting the slides. How can I do?#
) is the semantically correct way to refer to the page in its entirety, so if that is what you are referring to there are no better ways to express it, especially for the sake of search engines. It is possible however to use JavaScript for cleaning the address bar after clicking on any link that ends with an empty hash:
window.addEventListener("DOMContentLoaded", function () { var aEmptyHashLinks = document.querySelectorAll("a[href$=\"#\"]"); for (var nIdx = 0; nIdx < aEmptyHashLinks.length; nIdx++) { aEmptyHashLinks[nIdx].addEventListener("click", function (oEvt) { location.hash = ""; history.replaceState(null, "", this.href.split('#')[0]); oEvt.preventDefault(); }); } }, false);For a downloadable version, please see
js-add-ons/takefive-clean-empty-hash.js
.
history.replaceState()
method might not be available locally, but only when the page is hosted in a webserver. Please keep in mind that this script is alternative to js-add-ons/takefive-clean-history.js
."Victoria Typewriter"
font however asks for a fee for commercial use. So in this case you either contact them or choose another font (please have a look at dist/fonts
for possible alternatives). Here is their message:
Hello, you've just downloaded the "Victoria Typewriter" font (2021) which has been created by Lukas Krakora and is free for non-commercial use only.
If you'd like to use the font commercially please contact me at my email krraaa@yahoo.com to get an information about pricing.
I can add any extra characters or customize the font for purchasers of the commercial license.
Any donation from non-commercial users to my Paypal krraaa@yahoo.com is welcome.
You can find my other fonts on www.typewriterfonts.net
And my FB page is: facebook.com/typewriterfonts
Thank you.
Lukas Krakora
There is currently a bug in Chromium that causes the CSS to explode from user-agent defaults to applied styles on page load (discussion at crbug.com/332189 and crbug.com/167083). A way to fix it is to add
<script>"whatever";</script>
to the <head>
of the page (any text within double quotes will do).
To test weather your browser is affected by the bug you can visit lab.laukstein.com/bug/input.
z-index
collisionThe <article class="slide">
element has the z-index
property set to 10000
, hence no other elements within the document must have a z-index
higher than 10000
in order not to be displayed above the slides. If there is no way to prevent that, it is possible to assign a higher z-index
to the slides manually,
<article id="my-hashtag" class="slide" style="z-index: 99999;"> ... </article>
or nest them within a higher stacking context.
<div style="position: relative; z-index: 99999;"> <article id="my-hashtag" class="slide"> ... </article> </div>
For more details, see the table of all the internal z-indices
assigned by Take Five!.
Internet Explorer is not officially supported. It is possible to obtain some results by adding the following style sheet to the document (but you should seriously consider to abandon hope):
/* IE only */ @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { article.slide > nav:first-of-type a[href] { visibility: inherit !important; } }
<article>
elements containing the slides will not be visible on the screen unless activated via their hashtag. However they will not be invisible on the printed version of the page, so you should think carefully about which part of your page will host your galleries. Usually a dedicated section in the end works well.<nav>
, <aside>
and <footer>
elements preserve their original disposition on the printed page and small screens, so you should not feel indifferent to their order. On the printed page also the <header>
element preserves its original position.itemscope
attribute and microdata, please see schema.org. A lists of the main rel
attributes instead can be found here, while its extension, together with information about microformats, can be found here."slide"
class assigned to an <article>
element.