demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter.

featured articles

popular favourites

Customizing HTML5 Form Error Messages With JavaScript

HTML5 form elements provide explicit, definitive elements for different types of inputs on web pages, with support for native in-browser validation. However, that validation has a few disadvantages over traditional client-side approaches like JQuery:

  • HTML5 form elements are not validated as the user moves through the form, but only when the user clicks the submit button;

  • Perhaps more importantly, the errors provided by the browser are blandly generic, with messages such as “Please input the requested information” providing very limited guidance to the user.

For a long time I was under the impression that the browser’s native error messages could not be altered, but that’s not true: you can easily customize your HTML5 form’s feedback by using .

I’ve provided one method of doing so previously, using CSS3 and span elements. The technique shown here uses JavaScript to customize the browser’s own built-in validation errors, providing far more variation and power.

An HTML5 form element will undergo client-side validation if it has a required attribute. In our case, we’ll call our custom validation via a function on the form’s submit button:

  1. <label for=email>eMail<input type=email id=email name=email></label>
  2. <input type=submit onclick=validate()>

Right now, if the user pressed the submit button without completing the eMail field, the function will not be found, and browser will simply respond with “Please fill out this field”. The form deserves a more informative error message. First, we need to identify the input, via a script placed at the very end of the document:

  1. <script>
  2. var email = document.querySelector('#email');
  3. </script>

Rather oddly, JavaScript insists that in order to create your own custom validation message, the default message for each input must be deleted first:

  1. <script>
  2. var email = document.querySelector('#email');
  3. email.setCustomValidity('');
  4. </script>

Then, we test the validity of the input:

  1. <script>
  2. var email = document.querySelector('#email');
  3. email.setCustomValidity('');
  4. function validate() {
  5.       if (!email.validity.valid) {
  6.       email.setCustomValidity('This field is required');
  7.       }
  8. }
  9. </script>

If you try to complete the form at this stage, you’ll see your own custom error message inserted after pressing submit. This is a good start, but a little broad: the error will be the same no matter what the user enters, until they supply a valid eMail address. Let’s make a distinction between a blank value and one that is incomplete by changing the function slightly:

  1. function validate() {
  2.       if (!email.validity.valid) {
  3.             if (email.value.length == 0) {
  4.             email.setCustomValidity('This field is required');
  5.             } else {
  6.             email.setCustomValidity('This is not a valid eMail address');
  7.             }    
  8.       }
  9. }

Now the form will respond appropriately to different input states, rather than providing a generic error message. When the eMail address is correct, no error messages will be shown and the form will be submitted.

Conclusion

While it takes a little work, it’s very easy to insert your own custom error messages in HTML5 forms. There are many possible improvements to make to this approach, but perhaps the greatest – the fact that the JavaScript changes the content of the error while leaving the presentation of the messages unchanged – must be treated in a separate article, due to the somewhat complex and arcane CSS involved.

Using SVG as an Alternative To Imagemaps

To create a clickable map on a website – for example, to create a world map for an company with several international distribution centers –  imagemaps have been the traditional solution: bitmaps with linked “hotspots” written in . While this works, imagemaps have several significant limitations in modern web design:

  • Imagemaps take significant time to develop, due to the fact that the hotspots must be plotted by hand.

  • While you can scale the bitmaps that makes up the imagemap, the plotted points in HTML do not scale, “drifting” the hotspots out of registration with their associated visual area.

  • Bitmaps tend to drop in quality or have an uncomfortably large file size when they are scaled, making them inappropriate for websites.

As an alternative, I would suggest using , which avoids these limitations entirely:

  • Accurate SVG maps of every nation and the world are already available for free, (Wikipedfdia is a great resource) with plotted outlines that can easily be turned into hyperlinked hotspots.

  • As vector outlines, SVG files tend to be very small in file size.

  • As vectors, SVG can be infinitely scaled without loss in quality or lack of registration.

As an example, I’ll use a map of lower western Canada, edited in Adobe Illustrator from Wikipedia’s SVG file of a Canadian map, then cleaned up in a text editor. The start of the file looks like this:

  1. <svg version="1.1" xmlns=//www.w3.org/2000/svg"
  2. viewBox="0 0 525 365">
  3. <path id="ab" fill="#D3D3D3"
  4. d="M351.371,342.397c-55.342,1.268-49.207,1.742-54… />
  5. </svg>

Each path outlines the shape of a Canadian province.  They can be linked using standard <a> tags, with the href attribute supplemented with the xlink prefix that SVG requires, and the xlink namespace added to the root SVG element.

  1. <svg version="1.1" xmlns=//www.w3.org/2000/svg"
  2. viewBox="0 0 525 365"
  3. xmlns:xlink=//www.w3.org/1999/xlink">
  4. <a xlink:href=//travelalberta.com/">
  5. <path id="ab" fill="#D3D3D3 d="M351.371,342.397c-55
  6. … />
  7. </a>
  8. </svg>

If you try the SVG file in your browser, you’ll see that the link only becomes active when you’re over the area of each vector shape, shown by a cursor change. We want to provide a greater visual impact, and make the code more efficient at the same time. Removing the fill from each path, we recreate the appearence using an embedded style. As I’ve shown previously, you can address most any SVG element in a CSS declaration, just as you can :

  1. path { transition: .6s fill; fill: #D3D3D3; }
  2. path:hover { fill: #22aa22; }

(Vendor prefixes removed in order to save space).

Finally, to make the SVG imagemap responsive, in the same embedded stylesheet:

  1. svg { width:100%; }

Then, embed the SVG directly in the HTML page to take full advantage of the interaction you have built.

There’s a lot more that we can do with this, as I’ll show you in future articles: right now I would suggest this approach as an excellent replacement for many imagemap applications, with the usual limitation of IE: only IE9 and above support directly embedding SVG in web pages; all other browsers are fine.

Photograph of a model on a chair being sprayed by water

Basic CSS Borders

Every element can be provided with a basic border via , using one of 10 styles: none, hidden, solid, dashed, dotted, groove, ridge,  double, inset and outset. There are also three CSS3 border styles – wave, dot-dash, and dot-dot-dash – that are not yet supported in any browser.

The thickness of CSS borders is commonly defined in pixels, due to the fact that they are usually set to a “hairline” width in most site designs. Technically, border-width can be defined with any CSS measurement system supported by the browser, with the exception of percentages. The hue of a border can also be defined using any CSS color system, allowing for the possibility of semi-transparent borders.

The most common way of defining borders is as a shortcut of space-separated values:

  1. border:  style thickness color;

In the examples below I’ve added a small around of border-radius to show how the styles appear in a curve.

border: 4px solid #222
border: 4px dashed #222
border: 4px dotted #222
border: 4px groove #777
border: 4px ridge #777
border: 4px double #222
border: 4px inset #777
border: 4px outset #777

You’ll notice that double is particularly sensitive to thickness, distributing the amount given in the shortcut between the inner and outer edges and the space between them. ridge and groove are similarly sensitive to color, using derivatives of the hue set in the shortcut to tone the inner and outer edges. For that reason, using “pure” colors: white, black, some primary hues – is not suggested, as doing so diminishes the browser’s ability to create a decent visual effect. inset and outset are similarly limited, and look “hokey” unless applied subtly.

Borders can be applied to each side of an element separately using border-left, border-bottom, etc, using the same shortcut syntax. This can be broken down further: border-right-color and border-left-width, etc.

To give one example where this level of detail might be used in a page, creating a Polaroid frame for a photograph with borders as shown at the top of this article (in which the thickness of the bottom edge is different from the other three sides) might best be served by using CSS like the following:

  1. img#polaroid {  border: 25px solid #e8e8d3; border-bottom-width: 50px; }

Broadly speaking, has far greater control over border styles, but I will need to leave that for another article.

Photograph by Paul Cox, licensed under Creative Commons

I met a traveller from an antique land
Who said: Two vast and trunkless legs of stone
Stand in the desert. Near them, on the sand,
Half sunk, a shattered visage lies, whose frown,
And wrinkled lip, and sneer of cold command,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them and the heart that fed:
And on the pedestal these words appear:
"My name is Ozymandias, king of kings:
Look on my works, ye Mighty, and despair!"
Nothing beside remains. Round the decay
Of that colossal wreck, boundless and bare
The lone and level sands stretch far away.

Adding CSS To HTML Elements With JavaScript

As I explained in a previous article, one of the benefits of is that it can randomly traverse the DOM, making it easy for an element anywhere on a web page to respond to a click in another, unrelated of the document. The appearance of HTML content is still under the purview of , meaning that we must integrate the technologies together to create a cohesive whole. As we’ll see in future articles, this extends to using JavaScript to initiate CSS animations on HTML content.

Adding A CSS Property & Value To An Element With JavaScript

We’ll start with a simple example: let’s say we wanted to add a border on an element after clicking on a button. The markup is as follows:

  1. <blockquote id=ozymandius>
  2. I met a traveller from an antique land…
  3. </blockquote>
  4. <button>Ozymandius</button>

We want a click on the button to change the color of the text in the blockquote. I’ve already styled the page using CSS.

  1. blockquote#ozymandius {
  2. background: #000 url(ozymandius.jpg) no-repeat top right;
  3. background-size: contain;
  4. padding: 3rem 3rem 3rem 4rem; color: #fff;
  5. font-family: Papyrus, fantasy; border-radius: 5px;
  6. margin: 0; font-size: 1.3rem;
  7. text-shadow: 2px 2px 2px rgba(0,0,0,0.8);
  8. }

(Not shown: an @media query to modify the presentation of the blockquote at smaller screen sizes, and my CSS technique for fading background images).

As I’ve discussed, we can’t work “backwards” through the DOM with CSS as it is currently written: that’s the role of JavaScript. Neither should we try to write the JavaScript inline: it’s much more efficient to call a function.

  1. <button onclick="highlight()">Ozymandius</button>

The function will be written earlier in the page: preferably in the <head> of the document, just after the embedded stylesheet.

  1. <script>
  2. function highlight() {
  3. document.querySelector("#ozymandius").style.color = "red";
  4. }
  5. </script>

As you can see, changing the style of an element with JavaScript is simple: identify the part of the document you want to with document.querySelector or some other method, add both the style and css properties, and set it to the value you wish.

JavaScript Equivalents To CSS Can Be Tricky

If a CSS property consists of a single word, the JavaScript reference is the same. Things get more complex if the CSS property contains hyphens or multiple words: the equivalent JavaScript reference is concatenated and camelCased. For example:

CSS PropertyEquivalent JavaScript Reference
font-stylefontStyle
margin-bottommarginBottom
list-style-typelistStyleType

JavaScript CSS Prioritization

Taking this idea a step further, we’ll add a border to the element:

  1. function highlight() {
  2. document.querySelector("#ozymandius").style.border = "2px solid red";
  3. }

Note that the style imposed by JavaScript merges with the established CSS of the document: our JavaScript-infused style respects the fact that we set a border-radius set in the embedded stylesheet but no actual border, and combines the two presentational rules together.

Every CSS property you know is applicable after .style. While it is the fastest and most efficient method in JavaScript of adding styles to elements from the perspective of browser performance, writing a sequence of .style code lines can become a little overwhelming when you want to add more than one property at a time. To get around this, you have a few options.

Adding Bulk Presentational Rules With cssText

You can use cssText to add a block of CSS in one shot:

  1. function highlight() {
  2. var ozy = document.querySelector("#ozymandius");
  3. ozy.style.cssText = "border: 2px solid red; color: red;";
  4. }

(I’ve referenced the #ozymandius element as a variable to gain a little more room per line, not because it is required by cssText).

Note that CSS added to an element by JavaScript takes priority over any established CSS rules:

  1. ozy.style.cssText = "border: 2px solid red; color: red; border-radius: 40px";

After the button was clicked, the blockquote element would have a 2px thick red border with a corner radius of 40 pixels and red text. You can think of this in exactly the same way as ordinary CSS rules: a declaration coming later in a stylesheet affecting the same element takes precedence over previous style rules, all other things being equal.

Adding classes With JavaScript

For complex CSS changes, it’s usually easiest to add a CSS class that’s already present in the stylesheet:

  1. .highlight {  border: 2px solid red; color: red; }

Then add className to the element reference:

  1. function highlight() {
  2. var ozy = document.querySelector("#ozymandius");
  3. ozy.className = "highlight";
  4. }

Note that this will replace any classes already applied to the element. Like most JavaScript references, className can be used to both read and write to the DOM, so if you want to retain classes that were previously applied to the element, you need to concatenate the new class to any existing ones:

  1. function highlight() {
  2. var ozy = document.querySelector("#ozymandius");
  3. ozy.className = ozy.className + " highlight";
  4. }

(Note the space before the word highlight, necessary because multiple classes applied to an element are space-separated).

The Power of classList

Alternatively, if you’re not worried about older browsers (or are willing to use a shim for them) you can use the very powerful classList:

  1. ozy.classList.add("highlight");

(Note that highlight does not require an added space when it is added with classList).

classList makes it very easy to add and remove CSS classes with JavaScript, but its use is still rare due to its poor support in IE (only IE 10+: all other browsers have supported it for years). Historically, the lack of features like classList has been one of the reasons developers have tended to use JavaScript frameworks like JQuery; I’ll have more to say about classList in a future article.

These are all one-way changes, with no undo short of a page refresh; I will talk about toggled alterations to element styles in another article.

Note: it’s also possible to add entire dynamic stylesheets to web pages with JavaScript, which I’ve covered in a separate article. While unusual, you can also set an element’s id with JavaScript to take advantage of matching CSS rules.

Annual Spring-Summer Posting Slowdown

Photograph of berries covered in winter iceWith almost all of my classes completed, it’s time for my annual summer refresh. This blog will have a similar experience: so long as things go to plan, a new redesign will be rolled out by the end of May. In the meantime, I have several deeply delayed commitments, including writing a new book and an article for Smashing Magazine, together with some that I must attend to.

To that end, readers will find that updates here will become both less frequent and more varied over the next several months: two new articles a week rather than three to five, covering a greater range of subjects. While web development will remain my primary focus, I like to use the opportunity of spring and summer to stretch my intellectual percolations.

For those readers in the northern hemisphere, I hope you will enjoy both the warmth and diversion; for those in the south, I wish continued interest and a brief winter.

Photograph by monteregina, licensed under Creative Commons.

Vanishing Acts: The CSS :empty Selector

writers are the blind swordsmen of web development: we pen declarations and throw them at documents hoping that something might stick, but rarely are we aware of the specific content of a selected element: the question of how many words are in a paragraph, or if it contains any words at all, has traditionally been the responsibility of , , and other languages.

Very often server-side languages will be employed to fire dynamic content into HTML containers on a page. When such an operation fails, front-end developers deserve equal time to address the issue: rather than trying to code around a load problem using only JavaScript and PHP, we can add CSS to style the empty containers.

Treating the Mystery of the Empty Cell

Frequently are filled with dynamic data, but some cells in the table may have missing information. Usually, these cells are just left blank, but you might want to emphasize their lack of content in other ways.

A good example might be a table that shows the distances between cities. Naturally, there will be no mileage information between a city and itself, creating a series of empty cells.

Distances Between Cities On The Pacific Rim (miles)
AucklandPapeeteLos Angeles
Auckland25426518
Papeete25424114
Los Angeles65184114

The markup for the table is as follows (I’m using HTML5 shortcuts for speed):

  1. <table>
  2. <caption>Distances Between Cities On The Pacific Rim (miles)</caption>
  3. <col><col><col><col>
  4. <tr><th><th scope=col>Auckland<th scope=col>Papeete<th scope=col>Los Angeles
  5. <tr><th scope=row>Auckland<td><td>2542<td>6518
  6. <tr><th scope=row>Papeete<td>2542<td><td>4114
  7. <tr><th scope=row>Los Angeles<td>6518<td>4114<td></table>

This is a good use-case for :empty as the vacant cells must be included in order for the table to be valid and present well.  With :empty, targeting the cells that lack content is easy:

  1. td:empty { background: #777; }

Note the structure of the code at the very end of the table, with the closing </table> tag right next to the last, empty <td> element. If that was not the case, the sole <td> tag would be treated as being “open” and not empty. (An alternative approach would be an opening and closing <td></td> with no space between them).

While odd, it should also be noted that you can combine the :empty and :not selectors to style cells that are filled:

  1. td:not(:empty) { /* styles for filled cells */ }

This would be an unusual approach, as our assumption is that the majority of cells have content and can be addressed with a simple td selector, but it is still a valid approach in CSS.

Rehabilitating The Missing Link

Navigation for a site is often dynamically generated, sometimes incompletely. It’s possible to have space reserved for a link that never appears, or does so only fitfully. While this usually implies that your backend developers need to do more work, there’s a simple CSS solution that will make appear less like a gap-toothed smile in the interim:

  1. nav[role="navigation"] a:empty { display: none; pointer-events: none; }

This means that a link with an href attribute value but no content will not be rendered in the browser. So taking this output HTML:

  1. <nav role=navigation>
  2. <a href="contact.html">Home</a>
  3. <a href="contact.html">Contact</a>
  4. <a href="tools.html">Tools</a>
  5. <a href="classes.html"></a>
  6. </nav>

… and adding the CSS above, will result in the last, empty tag not appearing. (In this case pointer-events is somewhat redundant, as the link won’t appear at all, and can’t be clicked in any case, but it’s a useful backup technique).

:empty Exceptions

Note that whitespace between an opening and closing tag counts as character information, as do any tags inside the targeted element. So the following is not considered an empty element:

  1. <a href="classes.html"> </a>

Neither is this:

  1. <a href="classes.html"><span></span></a>

As mentioned above, tags that are not closed, even if doing so is optional in HTML, do not count as empty, even if they have no content. A single paragraph is “open”, and therefore not empty:

  1. <p>

Although such a tag with no carriage return between it and the next one would be:

  1. <p><p>

In the example above, the first paragraph would be empty, but the second (assuming nothing else came immediately after it) would not be.

“Self-closed” elements are counted as being empty: <br>, horizontal rules, <img>, etc will respond to :empty.

Elements are also counted as being empty if comments are their sole content:

  1. <p><!--this paragraph is empty --></p>

Using :empty as a visual QA test for code

Inevitably, some developers get lazy. “Hey, I need more space under this element. I know, I’ll just add an empty paragraph".

  1. <p>Some actual content…
  2. <p></p>

Or, even worse, a <br> tag. This empty, “filler" markup gets in the way of well-written CSS, while being notoriously difficult to track down. We can use :empty as a quick visual check of pages for vestigial markup:

  1. *:empty, br { border: 2px solid red; }

Browser support & conclusion

:empty has very good support: every modern browser, back to and including IE9, recognizes the selector.

There are many more possibilities for :empty: you’ll see one next month, in the redesign of this blog.

What Canada’s New CASL Laws Mean For Web Developers Worldwide

In 2010 Canada unveiled some of the toughest anti-spam legislation in the world. While now on the law books, the legislation has not yet come into full effect, pending the development of detailed regulations. This gives web developers time to adjust to the new provisions: a vital opportunity, as the law influences not just Canadian businesses, but the transmission of all pertinent information that touches servers in Canada, with fines up to 10 million dollars for non-compliance.

The Canadian Anti-Spam Legislation prohibits spamming, hacking, malware, online fraud, eMail harvesting and invasions of privacy. The most pertinent area for front-end developers is gaining consent for commercial electronic messages (CEMs).

While I am not a lawyer (and this article does not constitute legal advice) I would suggest that, pending detailed legal regulations, most front-end developers would do well to follow a few simple steps to ensure CASL compliance:

  • ensure that website forms make it clear why the information is being requested, who gains from it, and how the information will be used.

  • never use implied consent or “opt-out” forms. Ensure that agreements require explicit, “opt-in” action from users. For example: if you desire users to sign up for a newsletter, leave an open checkbox for them to click, rather than a pre-checked form element that assumes their consent.

  • provide easily accessible options for users to unsubscribe or remove themselves from databases.

  • provide clearly visible contact information for consumers as an avenue for questions.

CASL means to codify “fair dealing” with consumers and users: rather than trying to trick or trap them, by using honest and straightforward communication. It’s unfortunate that legislation is required to enforce common sense, but web developers who lack ethical considerations have made it necessary.

web developer guide

featured comment

by Aisling Brock in New Business Card Design

what i'm reading

A Feast for Crows: A Song of Ice and Fire: Book Four
A Feast for Crows: A Song of Ice and Fire: Book Four

what i'm watching

Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]
Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]

what i'm playing

Borderlands
Borderlands

what i'm hearing

Planets
Planets

blogs

podcasts

no ads ever

This blog is free of advertising, and always will be.

creative commons licensed

The content of this blog is free to use in whatever way you wish under the Creative Commons license.