Month: October 2011

HTML5 Details Element Enabler

According to WhatWG, the “<details /> element represents a disclosure widget from which the user can obtain additional information or controls“. In brief, you can use it to create panelbar elements without JavaScript, as the expand / collapse functionality is native to it. Currently (October, 2011), the only browser which supports <details /> is Google Chrome, so if you are eager to start using this element on your pages, you can do so with the help of a few lines of JavaScript to make sure it works on all browsers.

The implementation I am going to present today assumes YUI library, but it can also be accomplished easily with jQuery or with pure JavaScript. Basically, the most important part of the script is the feature detection:

if (!(OPEN in document.createElement("details"))) {
// enable expand / collapse with JavaScript for unsupported browsers
}

The code above will check for native availability of expand / collapse functionality, and if it is not present in the browser, it will bind click event to the <summary /> element that will toggle the open attribute of it’s parent – the <details /> element:

Y.one("body").delegate("click", function() {
var details = this.get('parentNode');

details.getAttribute(OPEN) ? details.removeAttribute(OPEN) : details.setAttribute(OPEN, OPEN);
}, "summary");

And the rest is just CSS:

details:not([open]) > div
{
display: none;
}

details[open] > div
{
display: block;
}

By using the :not() selector we make sure that if the open attribute is added by default to the <details /> element, its content will be expanded.

In case we need a custom expand / collapse arrow instead of the default one provided in Google Chrome we can hide it by using a proprietary pseudo element:

details summary::-webkit-details-marker
{
display: none;
}

… And then play with the ::before pseudo element of the <summary /> tag like this:

summary::before
{
content: "+";
}

details[open] summary::before
{
content: "-";
}

How to Use the HTML5 Details Enabler:

Script Assets:

<script src="http://yui.yahooapis.com/3.4.1/build/yui/yui-min.js"></script>
<script src="html-5-details-element-enabler/html-5-details-element-enabler.js"></script>

Stylesheet:

<link rel="stylesheet" href="html-5-details-element-enabler/html-5-details-element-enabler.css" />

Initializer:

YUI().use("html5-details", function (Y) {
var details = new Y.HTML5.Details();
details.enable();
});

The possibilities are numerous – you can apply cool transition effects for the expand / collapse, play with gradients and shadows, CSS3 makes most of the stuff really easy to achieve.

The HTML5 Details demo is here, and if you want to check other cool stuff, please, visit my experiments website.

Related Posts

Advertisements

Bootstrapping of Embedded Fonts to Prevent FOUT

A disclaimer before I start this post – the solution I will present works with best with AJAX applications and can be applied for elements that are not present when the page initially loads.

According to Paul IrishFOUT is what I’m calling the flash of unstyled text that you get while using @font-face in Firefox and Opera.” and this could be quite annoying. Fortunately, on the Internet there are a few good solutions. The issues with the correct (expected) and timely download and application of web-fonts are three:

  1. The actual download of an embedded font starts after the load event of the page;
  2. The downloading of the font will not start until the browser parser encounters elements on the page that atually need this font regardless of the fact that the font is registered in the stylesheet using the @font-face directive.
  3. The font downloading will not start on elements with initial display: none.

Recently I was working on a web project that required the use of embedded fonts, and as the design guys needed a really bullet-proof solution, none of the articles I found was really suitable. Luckily, the project was fully ajax-driven and the embedded fonts were used on elements that were not initially on the page, so the solution I came up with was pretty obvious and easy to achieve – I created a few hidden elements (one for each font), whose font properties required the embedded fonts when page is initially loaded and in this manner the browser was forced to start downloading the font files, so they were available for the “real” elements that needed them later.

The Markup:

<span class="font-loader">
<span class="embedded-font-regular"><!-- / --></span>
<span class="embedded-font-bold"><!-- / --></span>
</span>

The @font-face Directives:

@font-face
{
font-family: "EmbeddedFontRegular";
src: url("../fonts/embedded-font-regular.eot?") format("eot"),
url("../fonts/embedded-font-regular.woff") format("woff"),
url("../fonts/embedded-font-regular.ttf") format("truetype"),
url("../fonts/embedded-font-regular.svg#webfontPPfl10JY") format("svg");
font-weight: normal;
font-style: normal;
}

@font-face
{
font-family: "EmbeddedFontBold";
src: url("../fonts/embedded-font-bold.eot?") format("eot"),
url("../fonts/embedded-font-bold.woff") format("woff"),
url("../fonts/embedded-font-bold.ttf") format("truetype"),
url("../fonts/embedded-font-bold.svg#webfontV2lCDIXN") format("svg");
font-weight: normal;
font-style: normal;
}

The .font-loader rules:

.font-loader
{
visibility: hidden;
position: absolute;
}

.font-loader .embedded-font-regular
{
font-family: EmbeddedFontRegular, Arial, Sans-serif;
}

.font-loader .embedded-font-bold
{
font-family: EmbeddedFontBold, Arial, Sans-serif;
}

Notice that I used position: absolute and visibility: hidden instead of just display: none, because affected browsers would not start downloading the font resources for elements with display: none;

Finally, if you don’t want to add meaningless and non-semantic empty elements on the page, you can easily recreate the solution I have offered with JavaScript that will create the markup on the client from a simple array.

More CSS3, HTML5 and JavaScript experiments on this page.

CSS3 Element Reflections

Recently I was asked to find a CSS-only solution for image (or anything) reflections, and since the only browsers that support box reflections (-webkit-reflect) out of the box are Google Chrome and Apple Safari, I had to find a crossbrowser solution, and this is what I would like to present today.

The demo is available on this page. Find more experiments here.

Related Posts