Web Standards

Every Layout

Css Tricks - Tue, 06/18/2019 - 11:57am

Every Layout is a new work-in-progress website and book by Heydon Pickering and Andy Bell that explains how to make common layout patterns with CSS. They describe a lot of the issues when it comes to the design of these layouts, such as responsive problems and making sure we all write maintainable code, and then they’ve provided a handy generator at the end of each article to create our own little frameworks for dealing with these things.

They also have a complementary blog and one of the posts called "Algorithmic Design" caught my eye:

We make many of our biggest mistakes as visual designers for the web by insisting on hard coding designs. We break browsers’ layout algorithms by applying fixed positions and dimensions to our content.

Instead, we should be deferential to the underlying algorithms that power CSS, and we should think in terms of algorithms as we extrapolate layouts based on these foundations. We need to be leveraging selector logic, harnessing flow and wrapping behavior, and using calculations to adapt layout to context.

The tools for flexible, robust, and efficient web layout are there. We are just too busy churning out CSS to use them.

I’m looking forward to seeing where this project goes and how many more layouts these two end up documenting.

Direct Link to ArticlePermalink

The post Every Layout appeared first on CSS-Tricks.

How to Section Your HTML

Css Tricks - Tue, 06/18/2019 - 4:22am

It has been brought to our attention in the comments that some of the techniques used in this article result in a poor user experience for screen reader users. Daniel has updated the post accordingly with alternate markup in several of the examples and demos. We'll continue to make edits to address other things that others have noticed. Thanks for being such an awesome community where we can all learn and grow together.

The sectioning elements in HTML5 are <nav>, <aside>, <article>, and <section>. <body> is also kind of a sectioning element since all content lying inside of it is part of the default document section.

Here is a brief explanation of each sectioning element and how they are used:

  • <nav> - Equivalent to role="navigation". Major site navigation that consistently appears frequently across the site. Examples include the primary navigation, secondary navigation, and in-page navigation.
  • <aside> - Equivalent to role="complementary". Content that is only tangentially related (or not related) to the main content. Think of something like a sidebar with supplementary information, a note within an article, or the outer container for a list of related articles at the bottom of a blog post.
  • <article> - Equivalent to role="article". Content that is self-contained in that it makes sense on its own when taken out of context. That could mean a widget, a blog post or even a comment within a blog post.
  • <section> - Equivalent to role="region". Content that needs extra context from its parent sectioning element to make sense. This is a generic sectioning element that is used whenever it doesn’t make sense to use the other more semantic ones.

https://t.co/NAZMrlQ1O5

I added HTML comments with some explanation of changes I made.

— Adrian Roselli &#x1f5ef; (@aardrian) June 20, 2019

See the Pen
Mock up page layout v2 (sections article)
by Adrian Roselli (@aardrian)
on CodePen.

Contents

This is a very long article that I suspect you will want to come back to and reference multiple times. To make that easier, here is a list of all the article headings:

Jump to article heading
  1. When to use <nav>
    1. A <nav> is unnecessary around a search form
    2. Don’t use the word "nav" or "navigation" in the label
    3. Questions to ask yourself
    4. A <nav> doesn’t have to be a list of links
  2. Avoid nesting an <aside> inside an <aside>
  3. Article is like "Block"; Section is like "Element"
    1. Comments sections
  4. Don’t swap <div> for <section>
  5. Headers and footers
    1. What goes inside headers?
    2. What goes inside footers?
  6. Sectioning elements and the document outline algorithm
    1. No browser supports the document outline algorithm
  7. Sectioning content
  8. The <main> element
  9. You need to label your sections. Here are three methods.
    1. Method 1: Add an aria-label attribute
      1. The aria-label translation issue
      2. Positives
      3. Negatives
    2. Method 2: Add a <h#> element to it
      1. Heading placement
      2. Only one heading of the highest level per sectioning element
      3. The heading always comes first
      4. Making visually hidden section labels out of headings
      5. Headings are well-supported by structure analysis tools
      6. Positives
      7. Negatives
    3. Method 3: Use an aria-labelledby attribute
      1. Labels can be hidden without CSS
      2. Major portability issue
      3. No need to place the label near the sectioning element
      4. Turn non-heading elements into section labels
      5. Positives
      6. Negatives
  10. Only use one method at a time
  11. Adding section labels to our example layout
  12. Making Heading 1 be the first heading
  13. Concerns with the simplified outline algorithm spec
  14. Using aria on the example layout sectioning elements
    1. Using aria-label
    2. Using aria-labelledby
    3. Results of using aria
  15. What happens when you need h7?
  16. Does your site have a good structure?
  17. Download and use a screen reader
When to use <nav>

The <nav> element only ever needs to be used once per navigation block. Sub-navigation that is already contained inside a <nav> element does not need to be wrapped in a second <nav> element.

<nav aria-label="Primary"> <ul> <li><a href="#">Primary link</a></li> <li><a href="#">Primary link</a></li> <li> <a href="#">Primary link</a> <!-- <nav> element is *not* needed again here --> <ul> <li><a href="#">Secondary link</a></li> <li><a href="#">Secondary link</a></li> </ul> </li> </ul> </nav>

The <nav> element is intended for only major navigation blocks. "Major" is a very subjective term though. html5doctor.com has a pretty good explanation of when it is and isn’t appropriate to use <nav>, keep in mind that the following are opinions and not official W3C rulings:

The key phrase is ‘major’ navigation. We could debate all day about the definition of ‘major’, but to me it means:

  • Primary navigation
  • Site search
  • Secondary navigation (arguably)
  • In-page navigation (within a long article, for example)

While there isn’t any right or wrong here, a straw poll coupled with my own interpretation tells me that the following shouldn’t be enclosed by <nav>:

  • Pagination controls
  • Social links (although there may be exceptions where social links are the major navigation, in sites like About me or Flavours, for example)
  • Tags on a blog post
  • Categories on a blog post
  • Tertiary navigation
  • Fat footers

html5doctor.com (strikethrough mine)

Breadcrumbs are another piece of content that should be wrapped in a <nav> element as evidenced by this W3C breadcrumb HTML example.

A <nav> is unnecessary around a search form

I disagree with HTML5 Doctor’s opinion that a site search form should be wrapped in a <nav> element (thus why I crossed it out). <nav> is intended to be wrapped around navigation links, not a form. The site search actually has its own special role that defines it as a search landmark. If you add role="search" to the search <form> element, it is announced to screen reader users as a search landmark. Screen reader users will also be able to navigate to it when navigating via landmarks. If there are multiple search forms on the page, they should be differentiated using aria-label or aria-labelledby (more details on these attributes later). Don’t include the word "search" in the aria label though — that’s like saying "image of" in image alt text; it’s unnecessary. Instead, focus on what the search form is searching through. So, for the global site search, giving it aria-label="site" would be appropriate.

<!-- <nav> is not needed on a search form. --> <!-- role="search" is enough --> <form role="search" aria-label="site"> <label> <span>Search</span> <input type="search" /> </label> <buton type="submit">Submit</button> </form>

A role="search" form won’t appear in a document outline but I think this is okay considering search forms are often small and self-contained. It still gets the majority of benefits that you get from using sectioning elements. Adding a sectioning element to the mix bombards the screen reader user with messages telling them that it is a search form (one for the sectioning element, one for the search role, and one for the search input label).

Don’t use the word "nav" or "navigation" in the label

Like with role="search", adding "navigation" to the label of a <nav> element only results in a screen reader saying "navigation" twice.

<nav aria-label="primary navigation"> <!-- Screen reader: "primary navigation navigation landmark" --> </nav> <nav aria-label="primary"> <!-- Screen reader: "primary navigation landmark" --> </nav> Questions to ask yourself

That same HTML5 Doctor article lists two questions that you can ask yourself to help you figure out if something should be wrapped in a <nav> or not:

  • Would another sectioning element also be appropriate? If yes, maybe use that instead.
  • Would you add a link to it in a "skip to" block for accessibility? If not, then it might not be worth using a <nav> element.

In those cases where the navigation is too minor to justify the use of the <nav> element, <section> is most likely the element that you should use instead.

A <nav> doesn’t have to be a list of links

The most common use case for a <nav> is to wrap it around a list of links but it doesn’t have to be a list of links. If your navigation works in a different sort of way, you can still use the <nav> element.

<!-- Example taken from the <nav> element specification --> <!-- https://html.spec.whatwg.org/multipage/sections.html#the-nav-element:the-nav-element-5 --> <nav> <h1>Navigation</h1> <p>You are on my home page. To the north lies <a href="/blog">my blog</a>, from whence the sounds of battle can be heard. To the east you can see a large mountain, upon which many <a href="/school">school papers</a> are littered. Far up thus mountain you can spy a little figure who appears to be me, desperately scribbling a <a href="/school/thesis">thesis</a>.</p> <p>To the west are several exits. One fun-looking exit is labeled <a href="https://games.example.com/">"games"</a>. Another more boring-looking exit is labeled <a href="https://isp.example.net/">ISP&#x2122;</a>.</p> <p>To the south lies a dark and dank <a href="/about">contacts page</a>. Cobwebs cover its disused entrance, and at one point you see a rat run quickly out of the page.</p> </nav>

In this same vein, it’s okay to have small bits like intro text in the <nav> element as long as the primary focus of the content is on the navigation links. Introductory content is best placed inside a <header> in the <nav> element. I’ll go into more depth on headers and footers later.

<nav> <header> <h2>In this section</h2> <p>This is some intro text describing what you will find in this section.</p> </header> <ul> <li><a href="#">Sub section one</a></li> <li><a href="#">Sub section two</a></li> </ul> </nav> Avoid nesting an <aside> inside an <aside>

In the same way that <nav> shouldn’t really ever be nested inside another <nav> element, <aside> elements also tend not to be nested inside each other. <aside> is used to represent content that is tangentially related to the content around it. That means placing an aside inside an aside is basically announcing a tangent away from something that in itself is a tangent away from the main content.

<!-- Don't do this --> <aside aria-label="Side bar"> <aside> <h2>Share</h2> <ul> <!-- List of social media links --> </ul> </aside> <aside> <h2>Recommendations:</h2> <ul> <li> <article> <h2><a href="#">Related article title</a></h2> <p>Article description</p> </article> </li> <!-- List of recommended articles continues --> </ul> </aside> </aside>

If you have a sidebar that has multiple sections, don’t nest <aside> elements inside of <aside> elements like in the example above. Instead, make the sidebar a single <aside> and then use <section> (or another appropriate sectioning element) to create the different sections.

<!-- Do this instead --> <aside aria-label="Side bar"> <section> <h2>Share</h2> <ul> <!-- List of social media links --> </ul> </section> <section> <h2>Recommended articles:</h2> <ul> <li> <article> <h2><a href="#">Related article title</a></h2> <p>Article description</p> </article> </li> <!-- List of recommended articles continues --> </ul> </section> </aside> Article is like "Block"; Section is like "Element"

<section> and <article> are easy to get confused with one another. If you are familiar with "Block Element Modifier" (BEM) syntax, then an easy way to think of the difference between the two is that an <article> is a bit like the "B" (or "Block") in BEM. It is a container that stores self-contained content that still makes sense when placed in a different context. Individual tweets on Twitter and each list item on a search results page would be considered <article> elements.

<section> is like the "E" (or "Element") in BEM. It is a sub-section that requires context from its parent sectioning element to make sense. <section> is a generic catch-all sectioning element that you use when it doesn’t make sense to use the other sectioning elements. So, if in doubt, go with <section>.

Note that if something is styled as a "Block" in BEM, that doesn't automatically mean that it is an <article> element. Same goes for BEM "Elements" and <section> elements. The element of something should be based on the meaning of the content, not how the content looks.

Comments sections

Something that may surprise people is that individual comments on a blog post are also considered articles, even though they are in reply to the main blog post. The <article> element wrapping around the main blog post should also wrap around the comments section though. This is to represent that the comments go with the main article.

<article> <h1>I am an awesome blog post!</h1> <p>I am some body text content.</p> <section> <h2>Comments</h2> <ul> <li> <article> <h2>Username</h2> <p>This is the comment body text.</p> <footer> <p> Meta data like post date makes sense in either the header or the footer. </p> </footer> </article> </li> </ul> </section> </article> Don’t swap div for a section

Just because we have these fancy sectioning elements now, it doesn’t mean that the good old <div> element has lost all of its usefulness. <div> has no semantic meaning, so it is quite useful whenever we are altering the HTML purely for the sake of styling purposes.

Let’s say that we have a blog post contained inside an <article> element that we need to wrap in something for the sake of styling purposes.

<!-- I need a wrapper element --> <article> <h1>I am a blog post</h1> <p>I am some content</p> </article>

Reaching for the <section> element in this circumstance is not the right thing to do.

<!-- Do not do this --> <section class="wrapper"> <article> <h1>I am a blog post</h1> <p>I am some content</p> </article> </section>

Though <section> is technically a generic element, <div> is the far more appropriate option in this circumstance. This new wrapping container is not meant to have any semantic meaning behind it and that is exactly what <div> is designed to be used for.

<!-- Use a <div> if the element is only used for styling purposes --> <div class="wrapper"> <article> <h1>I am a blog post</h1> <p>I am some content</p> </article> </div>

Another way to remember this: if you can’t think of a meaningful heading to apply to a <section>, then it probably shouldn’t be a <section>.

Headers and footers

Although they don’t necessarily need to, sectioning elements may contain a single <header> and a single <footer> with the header being at the top of the section and the footer being at the bottom.

Sectioning elements can be nested inside one another as many times as is needed based on the content.

The header and footer in a sectioning element can also contain sectioning elements.

The one major restriction around nesting sectioning elements is that headers and footers cannot be nested inside other headers and footers.

Nesting headers and footers inside one another is not allowed. What goes inside headers?

Headers are used for introductory content. Appropriate things to include in <header> elements include (but are not limited to):

  • The heading element (<h1>-<h6>)
  • An introductory paragraph or statement.
  • A profile picture
  • A logo
  • A search form
  • Primary navigation
  • Author’s name
  • Post/updated date
  • Meta data
  • Social media links
What goes inside footers?

Footer elements primarily hold things like meta data and minor supporting content. Appropriate things to include in <footer> elements include (but are not limited to):

  • Copyright information
  • Legalities
  • Footnotes
  • Low priority site navigation
  • Author’s name
  • Post/updated date
  • Meta data
  • Social media links

You will notice that there is some cross over between the header and the footer in terms of content that is appropriate to both. This is mostly because meta-type content fits well in either element. It mainly comes down to the design that you are trying to achieve. <header> elements do tend to signify that the content inside of them is of greater importance than the content inside of a <footer> element though.

Sectioning elements and the document outline algorithm

An important thing to know about these sectioning elements is that they are all supposed to feature a <h#> element inside of them (or be labeled in some other way, but more on that later). This is primarily for the sake of something called the document outline algorithm. This is an algorithm that uses sectioning elements to help determine what level a heading (<h#>) should be without having to rely exclusively on the number that the developer has provided. So, have you ever wondered whether or not it’s okay to have more than one <h1> on a page? This is meant to make that a non-issue (but hold on for a sec, because there is more to the story).

<!-- No Document outline algorithm --> <article> <h1>Primary heading</h1> <h2>Secondary heading</h2> <p>Some text.</p> <h3>Tertiary heading</h3> <p>Some text.</p> </article> <!-- With document outline algorithm --> <article> <h1>Primary heading</h1> <!-- Recognized as <h1> --> <!-- sectioning element sets new heading level context --> <section> <h1>Secondary heading</h1> <!-- Recognized as <h2> --> <p>Some text.</p> <h2>Tertiary heading</h2> <!-- Recognized as <h3> --> <p>Some text.</p> </section> </article>

There is a lot more to learn about the document outline algorithm. I’ll stop here though because...

No browser supports the document outline algorithm

There is not a single browser that supports this method of creating a heading structure. This is a shame. It would make building accessible websites much easier if we didn’t have to worry so much about using the correct heading level all the time.

As far as I’m aware, there are two main reasons why no browser has implemented the algorithm. One is that browser vendors are afraid of breaking the heading structure of sites that have used sectioning elements incorrectly. The other reason is that the current document outline algorithm spec is difficult to implement and no browser vendor has been willing to put the time into implementing it yet.

In reference to the first reason, there is a long discussion about incorporating a new <h> element instead of using the <h1> element to tell browsers to use the document outline algorithm. I was in favor of this new <h> element idea until I realized that an attribute on the <html> element or adding a <meta> tag to the <head> would work even better as a means of telling browsers it was safe to use the algorithm. It is also better for headings to fall back to a <h1> in unsupported browsers than falling back to a <span>.

If you would like to play around with this <h> concept though, there is a plugin called hfill. It allows you to nest <hx> headings inside sectioning elements to create the document outline without having to worry about heading levels so much. There is a demo available for you to try it out. The major flaw in this plugin though is that the only way to increment heading levels is by nesting sectioning elements inside one another. There is no <h1>-is-greater-than-<h2> dynamic in this plugin which is the main reason I fell out of love with this <h> element idea. This lack of heading hierarchy would make CMS rich text editors far too difficult for clients to use.

As for the issue around implementation difficulty, work is being done to produce a simplified spec that browser vendors are more likely to adopt. The document outline algorithm has been in the HTML specifications for years. Hopefully this simplified spec will allow the algorithm to become a reality.

Although the algorithm is not supported anywhere yet, we can still build with the algorithm in mind. If we build with it in mind, then we gain the following benefits:

  1. We future-proof our sites in case the algorithm ever does get implemented.
  2. We can significantly improve the user experience for screen reader users.
  3. We potentially improve search engine optimization (SEO) due to search engines being able to better understand the site’s content.
  4. We can create a better user experience for users by allowing them to use native browser features that make use of sectioning elements, like Reader Mode.
Sectioning content

Take a look at this mock-up layout I put together and think about how you might split it up into sections.

This is how I would split the layout up into sectioning elements (only the solid lines represent sectioning elements).

In terms of HTML markup, it looks like this:

<body> <header> <a href="/" title="Go to home page"> <img src="logo.png" alt="Site logo"> </a> <nav> <ul> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> </ul> </nav> <form role="search" aria-label="site"> <label> <span>Search</span> <input type="search"/> </label> <button type="submit">Submit</button> </form> </header> <nav> <ul> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> </ul> </nav> <main> <article> <h1>Main article heading</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p> <h2>Article secondary heading</h2> <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p> <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p> </article> </main> <aside> <section> <h2>Share</h2> <ul> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Email</a></li> </ul> </section> <section> <h2>Recommended</h2> <ul> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> </ul> </section> </aside> <footer> <ul> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> </ul> </footer> </body> The <main> element

There is a very important semantic element that I used in the markup above that I haven’t covered yet and that is the <main> element. The <main> element represents the primary content of the page. It is not supposed to feature any side bars or navigation elements in it. You also must not have more than one <main> element on the page unless all other <main> elements on the page have a hidden attribute applied to them (this is for the sake of SPAs).

The <main> element is not a sectioning element. This means that it doesn’t help contribute to the document outline algorithm and it can’t feature a <header> or <footer> element as a direct child. It is a landmark element though so screen reader users are able to navigate to it quite easily.

I’m not 100% sure if using <article> in the <main> element like I have done above is necessary. Semantically, it does make sense. The main content is self-contained, thus justifying use of the <article> element in this way. From a document outline algorithm perspective, the <article> element also helps with the document structure.

From a usability point of view, it feels a bit unnecessary and the document outline algorithm doesn’t even work anywhere at the moment. I’m going to continue using it throughout my examples but I would be interested to know what other people think about this in the comments section.

You need to label your sections. Here are three methods.

I am going to be saying the word "label" a lot throughout this article. Keep in mind that I am not talking about the <label> element. The <label> element is not used to label sectioning elements.

Sectioning elements require labels so that screen reader users are able to quickly identify what content they can find inside that particular section of the site. I consider using sectioning elements without providing associated section labels as an accessibility fail, unless it is the only one of its type on the page. It is also recommended that the exact same label text not be used on multiple sectioning elements (or heading elements). This makes each section more recognizable to screen reader users which helps them navigate the site more easily.

There are three ways to label a sectioning element. In the following examples, I refer to "transport" and "portability" as a way of explaining how easy it is to save the section into a component and use that component multiple times in multiple different contexts.

I also provide lists of positives and negatives in the examples as well. In these lists, I assume that you want the section label to be readable by screen readers but hidden from sighted users.

Method 1: Add an aria-label attribute

This is the quickest and easiest way to label a sectioning element.

<section aria-label="Label for this section"> <p>Content for this section</p> </section> #The aria-label translation issue

The main draw back of aria-label (at the time of writing) is that most browsers are unable to translate these values for users who speak a different language than you. The developers at Google recently fixed this bug in Chrome, however this is still a problem for every other browser.

If your website has a large international audience or you know that many of your users do not speak your language, you should probably avoid using this attribute until all browsers support the translation of this property. If you don’t have those sorts of users, it’s pretty safe to assume that the non-sighted users viewing your site are able to understand your language — well enough to be able to navigate your site, anyway.

If you need more convincing, let's say your site has very few international users. That means your users generally come from the same country as you. If they come from the same country then they are likely to speak the same language as you, so there is already a fairly small percentage of your users that don’t understand the native language of your site. Now take into account that aria-label only affects screen reader users. That is now only a fraction of an already small percentage of your users who will experience the issue. And now consider that Chrome (by far the most popular browser in the world) now supports translation of the aria-label attribute. The user has to also not be using an up to date version of Chrome as their browser for the translation issue to be a problem. If you factor all of that together, it is highly probable that you may not have any users who are both able to perceive the aria-label attributes and are incapable of comprehending what they say. This makes me feel like the bad multi-lingual support in aria-label isn’t really worth worrying that much about unless you have a large international audience or you have many users that you know do not speak your language.

#Positives
  • Super quick and easy to implement.
  • Doesn’t affect heading structure.
  • Makes components easy to transport.
  • Is invisible to sighted users.
#Negatives
  • Not translated into other languages in non-Chrome browsers (at time of writing).
  • Often not supported by page structure analysis tools.
  • Confusion can arise from not knowing what level other headings inside the section should be at.
Method 2: Add a <h#> element to it

By <h#> I mean <h1>, <h2>, <h3>,<h4>,<h5>, or <h6> depending on what makes sense. Adding a heading to a sectioning element is a quick way to label it.

#Heading placement

The heading can be placed either directly in the sectioning element, like this:

<section> <h1>Heading</h1> <p>content</p> </section>

...or placed inside the <header> element:

<section> <header> <h1>Heading</h1> <p>I'm a byline</p> </header> <p>Content</p> </section>

You can also place as many <div> wrapper elements between the sectioning element and the heading as you want.

<!-- This is perfectly fine --> <section> <div> <header> <div> <h1>Heading</h1> <p>I'm a byline</p> </div> </header> <p>Content</p> </div> </section> #Only one heading of the highest level per sectioning element

There should really only be one heading of the highest level in a sectioning element. The spec says that when there are multiple top level headings or headings of a higher level than the first, the browser is supposed to close the previous sectioning element and start a new one of the same type.

The first element of heading content in an element of sectioning content represents the heading for that explicit section. Subsequent headings of equal or higher rank start new implied subsections that are part of the previous section’s parent section. Subsequent headings of lower rank start new implied subsections that are part of the previous one. In both cases, the element represents the heading of the implied section.

HTML 5.3, Headings and Sections

In reality, the browser uses the first heading as the section label but these implied sections are never created. It just announces the heading as is when it encounters it. It’s not earth-shatteringly bad but it is somewhat confusing.

<!-- Avoid this: --> <section> <h2>Heading level two labeling a section</h2> <p>Content</p> <!-- Don't use same level or higher headings as the one labeling the section --> <h2>This is also a heading level two</h2> <p>Content</p> </section> <!-- Do this instead: --> <div> <section> <h2>Heading level two labeling a section</h2> <p>Content</p> </section> <section> <h2>Heading level two labeling a different section</h2> <p>Content</p> </section> </div> #The heading always comes first

If a sectioning element has a <h#> element, that top level heading should always be the very first piece of content inside that sectioning element. Failing to do so counts as an accessibility fail.

If you find yourself needing to place content before your heading (like an image, for example), you can use Flexbox to rearrange the visual order. This will allow it to look like the image comes before the heading but in the markup the heading comes before the image. There is a bug in IE that will sometimes cause text to not wrap in a flex-direction: column; element. You can work around this issue by applying a max-width to the flex-child element.

<!-- Don't do this --> <section> <img src="image.jpg" alt="Don't place content or images before the heading" /> <h2>Headings should always come first</h2> <p>Place regular content after the heading</p> </section> <!-- Do this instead --> <section class="example"> <h2>Headings should always come first</h2> <img src="image.jpg" alt="Don't place content or images before the heading" /> <p>Place regular content after the heading</p> </section> <style> .example { display: flex; flex-direction: column; } .example img { order: -1; } </style>

Note that rearranging the visual order to satisfy WCAG Guideline 1.3.2: Meaningful Sequence can conflict directly with WCAG Guideline 2.4.3: Focus Order. For example, if that image is a link to an article and the heading you are placing it above is also a link to the article, placing the heading first breaks the focus order. Placing the image first breaks the meaningful sequence.

In situations like this where these two guidelines conflict with one another, my opinion is that the 1.3.2: Meaningful Sequence guideline is the more important guideline to follow if you aren’t able to resolve the conflict in some way. Failing focus order leads to the user suffering a moment of discomfort as they are tabbing through the content and focus is sent to an unexpected location. Failing to follow a meaningful sequence leads to a confused user unsure of the relationship between different bits of content.

#Making visually hidden section labels out of headings

Headings are visible to sighted users by default. This makes them super useful if you want the heading to be visible. A lot of the time, we don’t want the label for our sectioning element to be visible though. In order to stop our sighted users from seeing the label, we need to use some CSS.

<style> .visually-hidden { position: absolute; opacity: 0; pointer-events: none; } </style> <section> <h1 class="visually-hidden">Heading</h1> <p>content</p> </section> #Headings are well-supported by structure analysis tools

Headings also have a huge advantage for developers in that any page structure analysis tool that you can find will have support for them. This makes heading structures easy to test and debug. The other two section labeling methods have very poor support in testing tools. Not even the official W3C Validator service supports the alternatives at the moment. I posted an issue to have this fixed — please consider helping to fix the issue if you are good at coding in Java.

#Positives
  • Quick to implement.
  • Reliably appears in page structure analysis tools making it easy to test and debug.
  • All browsers will translate the text into other languages.
  • No confusion over what level other headings inside the section should be.
#Negatives
  • Affects document heading structure.
  • Need to ensure that the heading is at the correct level before use.
  • Visible to the user by default.
  • Requires CSS to hide the heading from visual users.
  • Can make components less portable due to heading structure requirements.
Method 3: Use an aria-labelledby attribute

This is what it looks like to create a hidden section label using aria-labelledby.

<section aria-labelledby="unique-id"> <div hidden id="unique-id">Label for this section</div> <p>Content for this section</p> </section> #Labels can be hidden without CSS

Note that I used the hidden attribute in the example to hide the div rather than a visually-hidden CSS class. aria-labelledby is able to read out text that is normally hidden from screen reader users. This adds the bonus effect of preventing the text from being read out twice by the screen reader. Don’t use the aria-hidden attribute though. Screen readers will not find the label text. Well, NVDA couldn’t find the label text when I tested it. I’m not sure about other screen readers.

#Major portability issue

aria-labelledby is the most difficult to use out of all the section labeling methods. The main aspect that makes it difficult to use is that the aria-labelledby attribute works off IDs. Things always get more complicated whenever IDs are involved. This is due to web pages only being allowed to have a single instance of an ID on the page at any one time. This makes component portability difficult.

Due to this portability issue, I would really only recommend this option if you need to support a multi-lingual audience and don’t want to mess around with the heading structure.

#No need to place the label near the sectioning element

You don’t need to place the element with the label text inside or near the section element that it labels. The text for the label can be placed in a completely different location to the sectioning element. This is thanks to the ID linking the two elements together. I’m not necessarily saying that it is a good idea to do this, but it is a feature of aria-labelledby that you should be aware of.

<div hidden id="unique-id">Label for this section</div> <!-- 1,000 lines of other HTML --> <section aria-labelledby="unique-id"> <p>Content for this section</p> </section> #Turn non-heading elements into section labels

There is one other key reason you may want to use aria-labelledby. If you have a visible non-heading element on the page that you want to use as the label for a section, aria-labelledby is perfect for this. A <legend> element inside a <fieldset> is a common use case for this. This doesn’t mean that you have to wrap fieldsets in sectioning elements. I’m just pointing it out in case you spot a need for it.

<section aria-labelledby="section_label"> <fieldset> <legend id="section_label"> I am both the fieldset legend and the section label </legend> <!-- Form fields go here --> </fieldset> </section> #Positives
  • All browsers will translate the text into other languages.
  • Can assign a non-heading element as the section label.
  • Text for the label does not need to be placed near the section it is labeling.
#Negatives
  • Requires the use of IDs to work.
  • Difficult to transport.
  • It can potentially be difficult to track down where the text for the label is stored in your source code.
  • Text is visible by default unless a hidden attribute is used.
  • Text might get read out twice by some screen readers if the text is not hidden.
  • Confusion can arise from not knowing what level other headings inside the section should be at.
Only use one method at a time

Don’t use a <h#>, an aria-label and/or an aria-labelledby attribute at the same time on the same sectioning element. Only every use one labeling method at a time for each sectioning element. Using multiple methods is super confusing and leads to the label being overwritten. It’s a bit like declaring the same property twice in CSS. I wasn’t sure how a screen reader would actually handle this so I created the most ridiculous <section> ever and ran it through NVDA.

<!-- Don't do this --> <section aria-label="Is this the section label?" aria-labelledby="is_this_the_label"> <h1>Or is this the section label?</h1> <p id="is_this_the_label">Only ever use one at a time.</p> </section>

This is the order of priority that NVDA gave to the various labeling methods from strongest to weakest:

  1. aria-labelledby
  2. aria-label
  3. <h#>
Adding section labels to our example layout

For a long time, I used headings as the only means of labeling sections. The poor multi-lingual support provided by aria-label scared me; and aria-labelledby was far too cumbersome to be my primary labeling method. We run into a bit of an issue though if we use only headings to label sections. I’ll show you what I mean.

<style> .visually-hidden { position: absolute; opacity: 0; pointer-events: none; } </style> <body> <header> <a href="/" title="Go to home page"> <img src="logo.png" alt="Site logo"> </a> <nav> <h2 class="visually-hidden">Primary</h2> <ul> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> </ul> </nav> <form role="search" aria-label="site"> <label> <span>Search</span> <input type="search"/> </label> <button type="submit">Submit</button> </form> </header> <nav> <h2 class="visually-hidden">Secondary</h2> <ul> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> </ul> </nav> <main> <article> <h1>Main article heading</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p> <h2>Article secondary heading</h2> <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p> <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p> </article> </main> <aside> <h2 class="visually-hidden">Sidebar</h2> <section> <h3>Share</h3> <ul> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Email</a></li> </ul> </section> <section> <h3>Recommended</h3> <ul> <li> <article> <h4><a href="#">Related article</a></h4> <p>Article description</p> </article> </li> <li> <article> <h4><a href="#">Related article</a></h4> <p>Article description</p> </article> </li> </ul> </section> </aside> <footer> <ul> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> </ul> </footer> </body>

If we look at our heading structure now, it will look like this (italics = visually hidden; bold = visible):

li.no-list-dot::before { display: none; }
    • <h2> Primary [nav]
    • <h2> Secondary [nav]
  • <h1> Main article heading
    • <h2> Article secondary heading
    • <h2> Sidebar
      • <h3> Share
      • <h3> Recommended
        • <h4> Related article
        • <h4> Related article

Notice that our <h1> heading isn’t at the top of the list? It really doesn’t feel right having two <h2> headings above the <h1> heading.

This form of heading structure is actually allowed by the W3C so it doesn’t count as an accessibility fail. I still think that this is a pretty bad UX for screen reader users though. It is not a logical progression from <h1> to <h2>. It makes the most sense if the first heading you encounter on the page is a <h1> then progress into <h2> then <h3> and so on.

Making Heading 1 be the first heading

For a very long time, I thought the absolute best way to handle this conundrum was to make the <h1> visually hidden and have it be the very first piece of content on the page. The thing that everyone thinks is the <h1> actually becomes a <h2>.

This is what that sort of structure looks like in practice:

<style> .visually-hidden { position: absolute; opacity: 0; pointer-events: none; } </style> <!-- Don't do this --> <body> <header> <h1 class="visually-hidden">Main article heading</h1> <a href="/" title="Go to home page"> <img src="logo.png" alt="Site logo"> </a> <nav> <h2 class="visually-hidden">Primary</h2> <ul> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> </ul> </nav> <form role="search" aria-label="site"> <label> <span>Search</span> <input type="search"/> </label> <button type="submit">Submit</button> </form> </header> <nav> <h2 class="visually-hidden">Secondary</h2> <ul> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> </ul> </nav> <main> <article> <h2><span class="visually-hidden">Body:</span> Main article heading</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p> <h3>Article secondary heading</h3> <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p> <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p> </article> </main> <aside> <h2 class="visually-hidden">Sidebar</h2> <section> <h3>Share</h3> <ul> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Email</a></li> </ul> </section> <section> <h3>Recommended</h3> <ul> <li> <article> <h4><a href="#">Related article</a></h4> <p>Article description</p> </article> </li> <li> <article> <h4><a href="#">Related article</a></h4> <p>Article description</p> </article> </li> </ul> </section> </aside> <footer> <ul> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> </ul> </footer> </body>

Now we have a document outline that looks like this (italics = visually hidden; bold = visible):

  • <h1> Main article heading
    • <h2> Primary [nav]
    • <h2> Secondary [nav]
    • <h2> Body: Main article heading
      • <h3> Article secondary heading
    • <h2> Sidebar
      • <h3> Share
      • <h3> Recommended
        • <h4> Related article
        • <h4> Related article

This mostly feels right. The <h1> is at the top and it all flows down perfectly with the <h2> elements representing major page sections and the <h3> elements representing sub sections. The main awkward bit is that the actual <h1> and the thing that everyone thinks is a <h1> are essentially duplicates of one another.

It wasn’t until I wrote up the first version of this article, had it nearly published, then had it thrown out the window, that I started to think differently. I talked with two accessibility consultants about the issue. They both agreed that, though this is a clever technical solution to the problem, it detracts from the experience of the very people that it is trying to help.

The issue is that when every other website in the world places the <h1> heading at the top of the main content area, that is what screen reader users come to expect. When your site is the special snowflake that does things differently, it confuses screen reader users and it takes them some time to figure out how your heading structure is supposed to work.

So, with that in mind, I’ve settled on a new method for handling the labeling of sectioning elements. Basically, any time I would have used a visually hidden heading, I would use an aria-label attribute now instead. If the site has a large non-native speaking audience, I would use aria-labelledby instead of aria-label.

Concerns with the simplified outline algorithm spec

If the simplified outline algorithm is approved in its current state, we will actually need to start structuring our sites like the visually hidden <h1> example anyway (just replace the <h2>, <h3> and <h4> elements with <h1> elements).

The original spec aimed to create the outline through the labeling of sectioning elements. This new spec is clearly aimed at trying to create the outline purely through heading levels. The algorithm basically calculates the heading level based on the number of ancestor sectioning elements a heading has plus the heading’s base heading level value. It's a bit more nuanced than that in the spec, but that is the general idea of how it works in simple terms.

The simplified algorithm currently makes no mention of aria-label or aria-labelledby. This means that those attributes will not help contribute to the document outline that the simplified algorithm generates. With a lack of aria-label support, this would mean labeling a sectioning element with aria-label could easily lead to skipped heading levels deeper in the tree.

<!-- Simplified algorithm skipped heading levels issue --> <body> <main> <h1>Primary heading for the page</h1> <!-- interpreted as <h1> --> <p>This is some content</p> </main> <!-- sectioning elements increase heading levels --> <aside aria-label="Side bar"> <!-- aria-label does not contribute --> <section> <h1>Share</h1> <!-- interpreted as <h3> --> <ul> <!-- list of social media links --> </ul> </section> <section> <h1>Recommended articles:</h1> <!-- interpreted as <h3> --> <ul> <!-- list of recommended articles --> </ul> </section> </aside> </body>

The simplified spec also considers it invalid to:

It does, however, allow for there to be more than one level 1 heading at the root of the document, which I find very odd and bad for accessibility (though my concern about this seems to have been ignored).

I have voiced the issues I have with the spec and proposed possible solutions in the GitHub discussion.

For the moment, it is still best to use aria-label and/or aria-labelledby attributes instead of visually hidden headings to label sectioning elements. It isn’t worth diminishing the experience of our present day users for the sake of a spec that hasn’t even been finalized or accepted yet.

Using aria on the example layout sectioning elements Using aria-label

This is what the HTML structure looks like if we use aria-label attributes to label the sectioning elements:

<body> <header> <a href="/" title="Go to home page"> <img src="logo.png" alt="Site logo"> </a> <nav aria-label="Primary"> <ul> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> </ul> </nav> <form role="search" aria-label="site"> <label> <span>Search</span> <input type="search"/> </label> <button type="submit">Submit</button> </form> </header> <nav aria-label="Secondary"> <ul> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> </ul> </nav> <main> <article> <h1>Main article heading</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p> <h2>Article secondary heading</h2> <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p> <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p> </article> </main> <aside aria-label="Sidebar"> <section> <h2>Share</h2> <ul> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Email</a></li> </ul> </section> <section> <h2>Recommended</h2> <ul> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> </ul> </section> </aside> <footer> <ul> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> </ul> </footer> </body>

Here is the layout in CodePen in case you want to have a play around with it (sorry mobile users, it's not mobile friendly):

See the Pen
Mock up page layout v2 (sections article)
by Daniel Tonon (@daniel-tonon)
on CodePen.

Using aria-labelledby

But let’s assume that you have a huge international audience that speaks all sorts of languages. In that case, it is better to use the aria-labelledby attribute. Here is what that would look like:

<body> <header> <a href="/" title="Go to home page"> <img src="logo.png" alt="Site logo"> </a> <nav aria-labelledby="primary-nav-label"> <div id="primary-nav-label" hidden>Primary</div> <ul> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> <li><a href="#">Primary nav</a></li> </ul> </nav> <form role="search" aria-labelledby="search-label"> <div id="search-label" hidden>Site</div> <label> <span>Search</span> <input type="search"/> </label> <button type="submit">Submit</button> </form> </header> <nav aria-labelledby="secondary-nav-label"> <div id="secondary-nav-label" hidden>Secondary</div> <ul> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> <li><a href="#">Secondary nav</a></li> </ul> </nav> <main> <article> <h1>Main article heading</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p> <h2>Article secondary heading</h2> <p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p> <p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p> </article> </main> <aside aria-labelledby="sidebar-label"> <div id="sidebar-label" hidden>Sidebar</div> <section> <h2>Share</h2> <ul> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Email</a></li> </ul> </section> <section> <h2>Recommended</h2> <ul> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> <li> <article> <h3><a href="#">Related article</a></h3> <p>Article description</p> </article> </li> </ul> </section> </aside> <footer> <ul> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> <li><a href="#">Footer link</a></li> </ul> </footer> </body> Results of using aria

The heading structure for the site at this point looks like this:

  • <h1> Main article heading
    • <h2> Article secondary heading
    • <h2> Share
    • <h2> Recommended
      • <h3> Related article
      • <h3> Related article

The document outline (assuming that the original outline algorithm is implemented) looks like this:

  • <body> Document
    • <nav> Primary
    • <nav> Secondary
    • <article> Main article heading
      • <section (implied)> Article secondary heading
    • <aside> Sidebar
      • <section> Share
      • <section> Recommended
        • <article> Related article
        • <article> Related article

You might be thinking that the document outline looks a bit bare. Shouldn’t things like the header and footer and search be announced in there as well? Keep in mind that this is just the explicit stuff. We get a lot of implicit information provided to the user for free by using correct HTML elements in a good structure. This is a simplified version of how a screen reader user might experience the site:

  • [Text used in the <title> element]
    • Banner landmark
      • Link, site logo [(on focus) "go to home page"]
      • "Primary" navigation landmark
        • [List of navigation links]
      • "Site" search landmark
    • "Secondary" navigation landmark
      • [List of navigation links]
    • Main landmark
      • "Main article heading" article landmark, heading level 1
        • [Content]
        • Heading level 2, "Article secondary heading"
          • [Content]
    • "Sidebar" complimentary landmark
      • "Share" region landmark, heading level 2
        • [List of share links]
      • "Recommended" region landmark, heading level 2
        • List with 2 items
          • Item, "Related article" article landmark, heading level 3
            • [Content]
          • Item, "Related article" article landmark, heading level 3
            • [Content]
    • Content info landmark
      • [List of footer links]

As you can see, the site structure becomes quite clear and understandable to screen reader users when you factor in all of the extra implicit information that you get from using a good HTML structure

So, even though no browser supports the document outline algorithm, it is still worth putting some effort into thinking about the outline. Screen readers still tell users what type of section something is, where sections start and (sometimes) end (depends on the screen reader), and what the section label is. This means that your efforts to make a good document structure do not go to waste.

This type of structure comes with multiple benefits:

  • The page is 100% compatible with the document outline algorithm, future proofing it in-case the algorithm is ever implemented in a real browser.
  • The heading structure is completely logical.
  • Screen reader users navigating via headings can quickly jump to important information.
  • Screen reader users navigating via landmarks have lots of useful landmarks to move about the page.
  • Screen reader users are able to quickly understand what each section contains without having to read any of the content inside of them.
  • Content is grouped into semantic sections, so screen reader users do not get confused when leaving one section and entering another.
  • Search engines are able to better understand what information each section holds, which could potentially improve SEO.
  • Sighted users can take advantage of native browser features like Reader Mode.
What happens when you need h7?

There is one more sticking point when it comes to labeling sectioning elements that I haven’t addressed yet. Let’s say you have somehow managed to use up all six native heading levels and are now stuck needing one more. What do you do?

You could use the aria-labelledby technique if it is just for the sake of labeling a section. Let’s say that you really want this heading to appear in the heading structure though, or maybe you just want to avoid using IDs as much as possible. Whatever the reason, you need an <h7> element but <h7> doesn’t exist.

This is when the aria-level attribute comes to the rescue. The aria-level attribute will define what the heading level should be for elements that have role="heading" applied to them. This is how the W3C recommend creating a <h7> element:

<div role="heading" aria-level="7">This is a valid heading level 7 element</div>

Not all screen readers support this syntax. I know that JAWS treats these like <h2> elements rather than <h7> elements. If you know of any screen readers that this doesn’t work in, please report the bug to the screen reader developer and also leave a comment down below.

When I need to reach for an <h7>, I’ll often use the implied role="heading" from an <h6> element instead. The aria-level attribute will override the implicit "6" level of the <h6> element. This isn’t exactly endorsed by the W3C though. It is cleaner and will allow the heading to still appear in document outline and heading structure testing tools (though they will typically appear as <h6> or <h2> level headings, not as <h7> level headings).

<h6 aria-level="7">This is also a valid heading level 7 element</h6>

By using aria-level, you now have access to an infinite number of heading levels!

Does your site have a good structure?

Now that you know how to do a proper HTML structure, are you able to apply what you have learned to your website?

I found a pretty good browser extension called "Headings Map" that is available for both Chrome and Firefox. This extension will allow you to easily see both a flat heading structure representation of your site (i.e. how all browsers currently read the heading structure) and what the document structure looks like in a browser that supports the document outline algorithm (i.e. how a theoretical future browser that supports the outline algorithm would present the site structure). The HTML5 Outline view needs to be enabled in the settings menu first. This is to prevent users from being fooled into thinking that they are able to use the outline algorithm in production sites.

Headings Map does not currently support the aria-label and aria-labelledby attributes on sectioning elements in the HTML5 outline tab. I have been talking with the developer and he is working on fixing this issue. If you know of a good document outline testing tool that already takes aria-label and aria-labelledby into account, please share a link to it in the comments.

Once you have a good document structure testing tool, check that both the heading structure and the document outline display a logical order with no missing headings or missing section labels anywhere.

Download and use a screen reader

The best way to test the implied semantics that you get from using correct HTML is to download an actual screen reader and try navigating your site with it. NVDA is one of the most used screen readers used by real screen reader users. It’s also free!

Be aware that the default settings for NVDA are optimized for usage by blind users. These default settings can drive sighted users insane. To enjoy your time using NVDA, perform the following steps (steps are based on a Windows set up, I don't have a Mac):

  1. Download NVDA and install it
  2. Create a shortcut to NVDA in your task bar (You will be opening and closing it regularly while testing)
  3. Open NVDA from the task bar
  4. Find NVDA in your system tray
  5. Right click the tray icon > "preferences" > "settings"
  6. Select "mouse" in the left panel
  7. Deselect "Enable mouse tracking" (You can now move your mouse without NVDA screaming at you)
  8. Press "OK"
  9. Right click the tray icon > "Tools" > "Speech Viewer" (You can now see a log of everything NVDA says, don't rely purely on this when testing though)
  10. In the Speech Viewer, check the "Show Speech Viewer on Startup" checkbox (It will open the Speech Viewer when you open NVDA)
  11. Familiarize yourself with some of the keyboard controls
  12. To close NVDA, Right click the tray icon > "Exit" > "OK"

NVDA currently doesn't support <article> and <section> elements. There is an issue on GitHub for supporting <article> elements. When I began writing this article <section> elements were already supported. Support for <section> seems to have dropped for some reason. This means NVDA should be fixed. It doesn't mean you should stop using the correct semantics in your HTML.

Build your website with the document outline in mind then test the semantics with Headings Map and NVDA (or another screen reader). If you do, you will make your screen reader users very happy. You might even make the search engines happier too. &#x1f60a;

Special thanks to Kevin Galvin (a principal consultant at me 2 accessibility) for advice around the usability issues of using a visually hidden <h1> element at the top of the page and suggesting aria-label as an alternative to using visually hidden headings.

The post How to Section Your HTML appeared first on CSS-Tricks.

If you can build a site with WordPress.com, you should build your site on WordPress.com.

Css Tricks - Tue, 06/18/2019 - 4:19am

That’s what I like to tell people. I’ve seen too many websites die off, often damaging the company along the way because the technical debt of hosting and maintaining the website is too much in the long term. For a few examples, there is the domain name itself to handle and the tricky DNS settings to go along with it. There is choosing and setting up web hosting, which often requires more long-term maintenance than many folks would like. There are SSL certificates that need to be handled and renewed. You’d better make sure security and backups and handled well, lest you risk the entire site.

Lots of stuff to think about!

Building and working on a website is hard enough without all this stress. These things are even hard enough work for seasoned web people, and often just too much entirely for people, projects, and companies that just want a dang website.

You know what? Do it on WordPress.com and worry about nothing. Just build your website and know that a great company has got your back on everything else.

To be clear, I’ve been working on websites for decades. I know a lot about what it takes to run them and what can break them. To anyone that wants to learn those things too, that’s great. I would never try to that away from anybody. And there are plenty of projects out there that need to do things that WordPress.com can’t do. But there are also a lot more projects out there suffering from forgotten web chores and abandoned responsibilities that would be and could be happily chugging along on WordPress.com.

Signing up for a WordPress.com site is not just easy, but even includes a free tier. It's pretty incredible how quick it is to get a site online. And, if you're at all familiar with publishing content on WordPress, then you know how simple it is to start cranking out content — and if you're new to WordPress, well, you're in for a treat because the editing experience is just plain delightful, especially with the new Gutenberg interface.

So, yes, regardless your skill level, type or business, team, or whatever, WordPress.com is an excellent resource and is the right call. Does it fit all use cases? No, but nothing does. I like the idea of choosing the right tool for the job and WordPress.com can certainly be the right choice for a good number of projects.

Oh and hey, as chance has it, the awesome WordPress Jetpack plugin happens to be having a 20% promotion. That's pretty awesome. If you've been following us for some time, then you know that we love Jetpack and use it right here on CSS-Tricks — from comment moderation to image optimization to social integrations and many things in between. Use coupon code JPSAVE20 at checkout.

The post If you can build a site with WordPress.com, you should build your site on WordPress.com. appeared first on CSS-Tricks.

Managing State in React using Unstated-Next

Css Tricks - Mon, 06/17/2019 - 4:29am

In a previous post, we saw how to manage state using Unstated. As you might recall, Unstated uses React’s built-in setState to allow you create components that can consume state by subscribing to a provider — like the React’s Context API.

Well, we’re going to build off that last post by looking at Unstated Next, a library that author Jamie Kyle identifies as the “spiritual successor" to his Unstated project. Unstated Next provides both React Hooks and the Context API for managing state. Unstated was a minimal abstraction to the idea of React Hooks before they were a fully-fledged thing. But now that Hooks in React are so good, that abstraction is unnecessary and Unstated Next simply incorporates them while providing an API to share state and logic with the Hooks.

We’re going to specifically look at how to manage state in both single and multiple components using Unstated Next. It might be helpful to check out the previous post on Unstated prior to moving ahead, but it’s not totally necessary.

Example: A minimal form component

To start off, we’ll create a tiny React application for a form that merely contains a text input for a person’s name and a button to submit it. When the button is clicked, we’ll display the name as a paragraph element above the form. The source code for this example is available on GitHub.

This is going to be a Bootstrap React application which we can spin up by using Create React App. Let’s install that and then change directories into the project folder.

npx create-react-app unstated-next-form cd unstated-next-form>

We need to add Unstated Next as a dependency:

## yarn yarn add unstated-next ## npm npm install --save unstated-next

We’ll be making use of React Hooks and createContainer from Unstated Next, so let’s import those into the App component:

// src/App.js import React, { useState } from 'react'; import { createContainer } from "unstated-next";

Next, we will create a custom hook. We’ll have our state in it, which we can create using useState:

// src/App.js // ...same as before const useForm = () => { const [input, setValue] = useState(""); const [name, setName] = useState("Barney Stinson"); const handleInput = event => { setValue(event.target.value); }; const updateName = event => { event.preventDefault(); setName(input); setValue(""); }; return { input, name, handleInput, updateName, }; };

We have two states defined here. input will be used for keeping track of values entered into the text input and it will be updated using the handleInput method. name will be updated when the button is clicked, which will trigger the updateName method.

OK, now we can create a container by passing our custom hook as a parameter to the createContainer() method.

// src/App.js // ...same as before const FormContainer = createContainer(useForm);

This will create a container which we can use across our application. Yeah, you read that right, but let’s take one step at a time. We’re starting with this one component to see how it works with Unstated Next.

Now, let’s create a Form component that looks like this.

// src/App.js // ...same as before const Form = () => { const form = FormContainer.useContainer(); return ( <div> <p>Hello! {form.name}</p> <div> <input type="text" value={form.input} onChange={form.handleInput} /> <button onClick={form.updateName}>Save</button> </div> </div> ); };

We’re assigning the variable form to the value obtained from calling FormContainer.useContainer(). The value contains the states and methods defined in the custom hook we created above. With that, we can make use of the state and methods provided — but for that to happen, we have to wrap the Form component in a provider.

const App = () => ( <Form.Provider> <Form /> </Form.Provider> )

With what you have learned so far, try building a minimal to-do application using Unstated Next. If you get stuck, feel free to check this repository to see how I made mine.

Example: Sharing state across multiple components

OK, so you got a hint earlier that we can use our form container anywhere we’d like. One of the benefits of using Unstated Next is that it makes it possible to share state across multiple components. To see how this works, we’ll build a tiny app that uses the form features we made above and also makes it possible to create to-do tasks using the same state. The name of the user can be updated in the form component, and this update will also be reflected in the to-do component. Two birds of a feather!

There’s a repo for this example as well, so feel free to clone or download it as we plow ahead.

Let’s spin up a new project and install the necessary dependencies:

npx create-react-app unstated-next-app cd unstated-next-app yarn unstated-next shortid

The state for the application will live in a separate file. We want to have the states for the form and to-do components in the store, and the methods needed for updating them too. Create a store.js file inside the src directory and make it look like this;

// src/store.js import { useState } from "react"; import shortid from "shortid" import { createContainer } from 'unstated-next' export const useStore = () => { // Construct a list that contains two default tasks const list = [ { id: 1, title: 'Write code' }, { id: 2, title: 'Buy milk' } ] const [input, setValue] = useState(""); // Let's set a legen -- wait for it -- dary default name that updates on form submit const [name, setName] = useState("Barney Stinson"); const [todos, addTodo] = useState(list); const [item, setTodo] = useState(""); const handleInput = event => { setValue(event.target.value); }; const updateName = event => { event.preventDefault(); setName(input); setValue(""); }; const handleTodo = event => { setTodo(event.target.value); }; const handleSubmit = event => { event.preventDefault(); const value = { id: shortid.generate(), title: item } addTodo(todos.concat(value)); setTodo(""); }; return { input, name, handleInput, updateName, todos, item, handleTodo, handleSubmit }; } export const StoreContainer = createContainer(useStore)

We make use of useState() to create the states we need. The methods are defined and all of this happens inside the custom hook, useStore(). We create the StoreContainer and then pass useStore() as a parameter to createContainer(). With that, we can make use of the StoreContainer in the necessary components where want to make use of the state and methods we have defined.

Starting with the form section, create a file called form.js and it should look like what I have below;

// src/form.js import React from "react"; import { StoreContainer} from "./store"; const FormComponent = () => { const form = StoreContainer.useContainer(); return ( <div> <p>Hello! {form.name}</p> <div> <input type="text" value={form.input} onChange={form.handleInput} /> <button onClick={form.updateName}>Change Name</button> </div> </div> ); }; export default FormComponent;

We’re using StoreContainer to access the state and methods we need. We’ll do the same thing for the task component which you can create in a todo.js file.

// src/todo.js import React from "react"; import { StoreContainer } from "./store"; const TodoComponent = () => { const todo = StoreContainer.useContainer(); return ( <div> <p>Add Todos</p> <input type="text" value={todo.item} onChange={todo.handleTodo} /> <button onClick={todo.handleSubmit}>Add</button> <div> <p>Dear {todo.name}, here are your current tasks;</p> {todo.todos.map((item) => { return ( <ul key={item.id}> <li>{item.title}</li> </ul> ); })} </div> </div> ); }; export default TodoComponent;

You can see that todo.name can only be updated in the FormComponent. That’s because we need a way to provide the state in both components. That’s why we’re going to turn again to Provider and add one in the App component just like we did in the previous example.

import React from 'react'; import TodoComponent from "./todo"; import FormComponent from "./form"; import { StoreContainer } from "./store" function App() { return ( <div className="App"> <StoreContainer.Provider> <FormContainer /> <TodoContainer /> </StoreContainer.Provider> </div> ); } export default App;

There we go! By adding the provider, data can be taken from the form component, stored in the provider, and passed back to the task list. &#x1f4a5;

The post Managing State in React using Unstated-Next appeared first on CSS-Tricks.

Components, yo.

Css Tricks - Fri, 06/14/2019 - 3:57am

I see VuePress just went 1.0. Explained simply, it's a static site generator based on Vue. But of course, you work in Vue, which means you work in components.

All the modern JavaScript frameworks are component-based. Even when they disagree with each other about specific things (like how Svelte requires compilation), they all seem to agree on the model of working in components. React is all components. A popular static site generator for React is Next.js. The Vue version of that is Nuxt.js.

Then there is Gatsby which is all React. (Listen to our latest ShopTalk Show as we discuss it.) Gridsome seems like the most 1-to-1 comparison in Vue-land, the notable comparison being how they both are designed to suck in data from any source. Components though, of course. I'm not sure there is a flagship Angular-based static site generator, but they are out there, and Angular is components all the way down.

Components are so ubiquitous that perhaps you don't even think about it anymore. But you might feel it, particularly if you jump back and forth between projects that aren't component-driven. WordPress development, generally, I feel, isn't component driven. Sure, you've got your header.php and footer.php files and such. You can break those apart however you want, but it's rather ad-hoc. You aren't explicitly building components and feeding those components local data and testing them as such. (You can get a lot closer with something like Timber.)

Building front-ends out of server-side code is absolutely fine. Server-side rendering is rife with advantages. But server-side languages don't seem to have embraced components the way JavaScript has. And since everyone seems to like components (front-end devs obviously love it, designers think that way anyway, back-end devs understand it...) it's no surprise to me to see this surge of beloved projects build server-side (or build-time) generated sites from JavaScript, simply because it's component-based and components are just a good idea.

The post Components, yo. appeared first on CSS-Tricks.

Weekly Platform News: CSS Scroll Snap, Opera GX, PWA Install Icon

Css Tricks - Fri, 06/14/2019 - 3:53am

Šime posts regular content for web developers on webplatform.news.

In this week's roundup, Chrome is adding an install option for Progressive Web Apps, Opera GX comes to Windows, the ECMAScript proposals get an update, and CSS Scroll Snap is coming to a Firefox browser near you.

An install icon is coming to Chrome on desktop

Pete LePage: The next version of Chrome will automatically show an install icon in the address bar on desktop if the site meets Chrome’s PWA "installability" criteria. You can listen for the appinstalled event to detect if the user installed your PWA.

Opera GX is available on Windows

Maciej Kocemba: The preview version of Opera GX for Windows is now available. This is a special version of Opera that lets users limit how much CPU and RAM is available to the browser.

Updated ECMAScript proposals

Azu The JavaScript optional chaining operator (obj?.prop) and null-ish coalescing operator (x ?? y) proposals have been moved to Stage 2 of the TC39 process. (See Web Platform News issue 902 for more information about the TC39 process.)

// BEFORE let text = response.settings && response.settings.headerText; if (text == null) text = "Hello, world!"; // AFTER let text = response.settings?.headerText ?? "Hello, world!"; CSS Scroll Snap is coming to Firefox

Šime Vidas: CSS Scroll Snap is supported in Chrome, Safari, and the next version of Firefox. Scroll snapping works well on touch screen devices but there are some usability issues on desktop platforms.

The post Weekly Platform News: CSS Scroll Snap, Opera GX, PWA Install Icon appeared first on CSS-Tricks.

Drawing Realistic Clouds with SVG and CSS

Css Tricks - Thu, 06/13/2019 - 4:17am

Greek mythology tells the story of Zeus creating the cloud nymph, Nephele. Like other Greek myths, this tale gets pretty bizarre and X-rated. Here’s a very abridged, polite version.

Nephele, we are told, was created by Zeus in the image of his own beautiful wife. A mortal meets Nephele, falls in love with her and, together, they take an adult nap™. Finally, in a strange twist, the cloud gives birth to half-human half-horse Centaur babies.

Weird, right??Personally, I can’t make heads or tails of it. Thankfully, the process for creating clouds in the browser is much more straightforward and far less risqué.

Yuan Chuan’s clouds detail. (Demo)

Recently, I discovered that developer Yuan Chuan has realized code-generated, photorealistic clouds. For me, this notion in the browser had long been the stuff of myth.

With one glance at the code in this pen we can imagine that convincing individual clouds are achievable through the use of CSS box-shadow with a <filter> element containing two SVG filters as its complement.

The photorealism we want is achieved with a delicate mix of feTurbulence and feDisplacementMap. These SVG filters are powerful, complex and offer very exciting features (including an Oscar winning algorithm)! However, under the hood, their complexity can be a bit intimidating.

While the physics of SVG filters is beyond the scope of this article, there is ample documentation available on MDN and w3.org. A very informative page on feTurbulence and feDisplacement is freely available (and offered as a chapter of this amazing book).

For this article, we will focus on learning to use these SVG filters to get spectacular results. We don’t need to delve too deeply into what is happening behind the scenes algorithmically, much in the way an artist isn’t required know the molecular structure of paint to render a stunning landscape.

Instead, let's pay close attention to small handful of SVG attributes that are essential for drawing convincing clouds in the browser. Their use will enable us to bend these powerful filters to our will and learn how to customize them with precision in our own projects.

Let’s start with some basics

The CSS box-shadow property has five values that deserve close attention:

box-shadow: <offsetX> <offsetY> <blurRadius> <spreadRadius> <color>;

Let’s crank these values up (probably higher than what any sane developer would so that this shadow becomes a player on the stage in its own right.

(Demo) #cloud-square { background: turquoise; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; } #cloud-circle { background: coral; border-radius: 50%; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; }

You’ve either made or seen shadow puppets, right?

Credit: Double-M

In the same way that a hand changes shape to alter the shadow, a "source shape" in the our HTML can move and morph to move and alter the shape of a shadow rendered in the browser. box-shadow duplicates the "morphing" features on the original size and border-radius. SVG filters get applied to both the element and its shadow.

<svg width="0" height="0"> <filter id="filter"> <feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="10" /> <feDisplacementMap in="SourceGraphic" scale="10" /> </filter> </svg>

This is the markup for our SVG so far. It won’t render because we haven’t defined anything visual (not to mention the zero width and height). It’s sole purpose is to hold a filter that we feed our SourceGraphic (aka our <div>). Our source <div> and its shadow are both being distorted independently by the filter.

We’ll add the essential CSS rule linking the HTML element (`#cloud-circle`) to the SVG filter using its ID:

#cloud-circle { filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; } Et Voilà!

OK, so admittedly, adding the SVG filter is pretty underwhelming.

(Demo)

No worries! We have only just scratched the surface and have a lot more good stuff to look at.

Experimenting with the feDisplacementMap scale attribute

A few un-scientific experiments with this one attribute can yield dramatic results. For the moment, let’s keep the all values in feTurbulence constant and simply adjust the scale attribute of DisplacementMap.

As scale increases (by increments of 30) our source <div> becomes distorted and casts a shadow to mirror the stochastic form in which clouds appear in the sky.

<feDisplacementMap in="SourceGraphic" scale="180"/> The scale attribute incremented by values of 30. (Demo)

OK, we’re getting somewhere! Let’s change the colors a bit to produce a more convincing cloud and to "sell" the effect.

body { background: linear-gradient(165deg, #527785 0%, #7FB4C7 100%); } #cloud-circle { width: 180px; height: 180px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }

Now we’re getting closer to a realistic cloud effect!

Modifying the box-shadow blur value

The following suite of images shows the influence that the blur value has on box-shadow. Here, blur is increased by 10 pixels incrementally.

The cloud becomes "softer" as the blur value increases.

To give our cloud a bit of a cumulus-like effect, we can widen our source <div> a bit.

#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 60px 0px #fff; } Great, now the source element is getting in the way. &#x1f62b;

Wait! We’ve widened the source element and now it’s in the way of our of the white shadow we’re calling a cloud. Let’s "re-cast" the shadow at a greater distance so that our cloud is no longer obscured by the source image. (Think of this as moving your hand away further from the wall so it doesn’t block the view of your shadow puppet.)

This is nicely achieved with a bit of CSS positioning. The <body> is the parent element for our cloud, which is statically positioned by default. Let’s "tuck" our source <div> up and out of the way with some absolute positioning. Initially, that will reposition our shadow as well, so we’ll also need to increase the distance of the shadow from the element and nudge the element a bit more.

#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 400px 400px 60px 0px #fff; /* Increase shadow offset */ position: absolute; /* Take the parent out of the document flow */ top: -320px; /* Move a little down */ left: -320px; /* Move a little right */ }

Yes! We've arrived at a pretty persuasive cloud.

See the Pen
by Beau Haus (@beauhaus)
on CodePen.

What is painted to the browser is a pretty decent depiction of a cloud–But, I’m not sure…does this cloud really do justice the cloud nymph, Nephele? I'm sure we can do better!

Conveying depth with layers

Here’s what we want:

Credit: pcdazero

From the look of the depth, texture and richness of the clouds in this photograph, one thing is clear: Zeus went to art school. At the very least, he must have read the The Universal Principles of Design which illustrates a powerful–yet, deceptively ordinary–concept:

[...] lighting bias plays a significant role in the interpretation of depth and naturalness, and can be manipulated in a variety of ways by designers...Use the level of contrast between light and dark areas to vary the appearance of depth.

This passage provides for us a hint as to how to we can vastly improve our own code-generated cloud. We can render our cloud with a good deal of fidelity to the clouds in our reference image by stacking layers of differing form, size and color on top of each other. All that takes is calling our filter as many times as we want layers.

<svg width="0" height="0"> <!-- Back Layer --> <filter id="filter-back"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" /> <feDisplacementMap in="SourceGraphic" scale="170" /> </filter> <!-- Middle Layer --> <filter id="filter-mid"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /> <feDisplacementMap in="SourceGraphic" scale="150" /> </filter> <!-- Front Layer --> <filter id="filter-front"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /> <feDisplacementMap in="SourceGraphic" scale="100" /> </filter> </svg>

Applying our layers will afford us an opportunity to explore feTurbulence and realize its versatility. We’ll choose the smoother type available to us: fractalNoise with numOctaves cranked up to 6.

<feTurbulence type="fractalNoise" baseFrequency="n" numOctaves="6"/>

What does all that mean? For now, let’s focus specifically on the baseFrequency attribute. Here’s what we get as we increase the value of n:

The lower the value, the rounder and fuzzier we get. The higher the value, the rounder and more rigid we get.

Words like turbulence, noise, frequency, and octave may seem odd and even confusing. But fear not! It’s actually perfectly accurate to analogize this filter’s effects to sound waves. We may equate a low frequency (baseFrequency=0.001) with a low, muffled noise and a rising frequency (baseFrequency=0.1) with a higher, crisper pitch.

We can see that our sweet spot for a cumulus-like effect may lie comfortably around the ~0.005 and ~0.01 range for the baseFrequency.

Adding detail with numOctaves

Incrementing numOctaves allows us to render our image in extremely granular detail. This requires a great deal of calculation, so be warned: high values are a significant performance hit. Try to resist the temptation to pump up this value unless your browser is wearing a helmet and knee-pads.

The higher the value we put into numOctaves the more granular detail give to our cloud.

The good news is that we don’t have to crank this value too high in order to produce detail and delicacy. As the array of images above shows, we can satisfy ourselves with a numOctavesvalue of 4 or 5.

Here’s the result

See the Pen
by Beau Haus (@beauhaus)
on CodePen.

Infinite variety with the seed attribute

There is much to say about the seed attribute as it offers a hint into the magic happening behind the scenes. But, for our purposes, the utility of seed can be reduced to four words: "different value, different shape."

The Perlin Noise function (mentioned earlier) uses this value as the starting point for its random number generator. Choosing not to include this attribute will default seed to zero. When included, however, whatever value we give seed, we don’t need to worry about a performance hit.

Different seed values produce different shapes.

The GIF above represents some of what seed has to offer. Keep in mind that each of those clouds is a layered, composite cloud. (While I have tweaked attributes for each layer, I have kept their respective seed values uniform.)

Credit: Brockenhexe

Here, with a close look at the reference image, I've layered 3 cloud-<div>s (of differing in opacity) onto a single base div. Through trial and error and punching in arbitrary seed values, I eventually arrived at a shape resembling the shape of the cloud in the photograph.

See the Pen
Nephele Reference Image study
by BEAU.HAUS (@beauhaus)
on CodePen.

Sky’s the limit

Of course, it would be hubris to think that the <div>s that we paint to the browser could be superior to Zeus’s, Nephele.

However, the more mystery we are able to tease out of CSS and SVG filters, the more we are empowered create something visually stunning with a high degree of fidelity to the Thunder God’s original creation. We can, then, can go on experiment further!

Reflecting Mist

Animated Reflecting mist

Alto-Cirrus Clouds

Alto-Cirrus clouds

In this article, we have just dipped our toe in an ocean of power and complexity. SVG filters can often seem overwhelming and unapproachable.

However, much like the examples found in the A Single Div project project or Diana Smith's painting techniques, a playful and experimental approach will always rewarded with spectacular results!

I hope this gets you excited about creating a bit of photorealism on the web. I developed a little tool to help put them all to use and experiment a bit. Any questions, suggestions or advice? Ping me in the twitterverse drop a comment here.

Many thanks to Amelia Bellamy-Royds for her kind advice on this article.

The post Drawing Realistic Clouds with SVG and CSS appeared first on CSS-Tricks.

A11Y with Lindsey

Css Tricks - Thu, 06/13/2019 - 4:16am

Lindsey Kopacz has a wonderful blog about accessibility. I've seen a number of her articles making the rounds lately and I was like, dang I better make sure I'm subscribed. For example:

Regarding that last one, I remember learning from Sara Soueidan that a good tip for this to position them over the new custom checkboxes and hide them via opacity instead of hiding the native checkboxes by clipping them away. That covers the scenario of people exploring a touch screen for native interactive elements.

The post A11Y with Lindsey appeared first on CSS-Tricks.

Grid, content re-ordering and accessibility

Css Tricks - Wed, 06/12/2019 - 4:13pm

Take this:

<ol> <li>Get hungry</li> <li>Order pizza</li> <li>Eat pizza</li> </ol>

That HTML ends up in the DOM that way (and thus how it is is exposed to assistive technology), and by default, those list items are also visually shown in that order. In most layout situations, the visual order will match that DOM order. Do nothing, and the list items will flow in the block direction of the document. Apply flexbox, and it will flow in the inline direction of the document.

But flexbox and grid also allow you to muck it up. Now take this:

ol { display: flex; flex-direction: row-reverse; }

In this case, the DOM order still makes sense, but the visual order is all wrong. It's not just row-reverse. There are a number of flexbox and grid properties that can get involved and confuse things: the order property, flowing items into columns instead of rows, and positioning items specifically in unusual orders, among others. Even absolute positioning could cause the same trouble.

Manuel Matuzovic says:

If the visual order and the DOM order don’t match, it can irritate and confuse users up to a point where the experience is so bad that the site is unusable.

Rachel Andrew highlights this issue (including things we've published) as a big issue, and hopes we can get tools at the CSS level to help.

I think this is something we sorely need to address at a CSS level. We need to provide a way to allow the tab and reading order to follow the visual order. Source order is a good default, if you are taking advantage of normal flow, a lot of the time following the source is exactly what you want. However not always, not at every breakpoint. If we don’t give people a solution for this, we will end up with a mess. We’ve given people these great tools, and now I feel as if I’m having to tell people not to use them.

Direct Link to ArticlePermalink

The post Grid, content re-ordering and accessibility appeared first on CSS-Tricks.

Using Cypress to Write Tests for a React Application

Css Tricks - Wed, 06/12/2019 - 4:07am

End-to-end tests are written to assert the flow of an application from start to finish. Instead of handling the tests yourself — you know, manually clicking all over the application — you can write a test that runs as you build the application. That’s what we call continuous integration and it’s a beautiful thing. Write some code, save it, and let tooling do the dirty work of making sure it doesn’t break anything.

>Cypress is just one end-to-end testing framework that does all that clicking work for us and that’s what we’re going to look at in this post. It’s really for any modern JavaScript library, but we’re going to integrate it with React in the examples.

Let’s set up an app to test

In this tutorial, we will write tests to cover a todo application I’ve built. You can clone the repository to follow along as we plug it into Cypress.

git clone git@github.com:kinsomicrote/cypress-react-tutorial.git

Navigate into the application, and install the dependencies:

cd cypress-react-tutorial yarn install

Cypress isn’t part of the dependencies, but you can install it by running this:

yarn add cypress --dev

Now, run this command to open Cypress:

node_modules/.bin/cypress open

Typing that command to the terminal over and over can get exhausting, but you can add this script to the package.json file in the project root:

"cypress": "cypress open"

Now, all you have to do is do npm run cypress once and Cypress will be standing by at all times. To have a feel of what the application we’ll be testing looks like, you can start the React application by running yarn start.

We will start by writing a test to confirm that Cypress works. In the cypress/integration folder, create a new file called init.spec.js. The test asserts that true is equal to true. We only need it to confirm that’s working to ensure that Cypress is up and running for the entire application.

describe('Cypress', () => { it('is working', () => { expect(true).to.equal(true) }) })

You should have a list of tests open. Go there and select init.spec.js.

That should cause the test to run and pop up a screen that shows the test passing.

While we’re still in init.spec.js, let’s add a test to assert that we can visit the app by hitting http://localhost:3000 in the browser. This’ll make sure the app itself is running.

it('visits the app', () => { cy.visit('http://localhost:3000') })

We call the method visit() and we pass it the URL of the app. We have access to a global object called cy for calling the methods available to us on Cypress.

To avoid having to write the URL time and again, we can set a base URL that can be used throughout the tests we write. Open the cypress.json file in the home directory of the application and add define the URL there:

{ "baseUrl": "http://localhost:3000" }

You can change the test block to look like this:

it('visits the app', () => { cy.visit('/') })

...and the test should continue to pass. &#x1f91e;

Testing form controls and inputs

The test we’ll be writing will cover how users interact with the todo application. For example, we want to ensure the input is in focus when the app loads so users can start entering tasks immediately. We also want to ensure that there’s a default task in there so the list is not empty by default. When there are no tasks, we want to show text that tells the user as much.

To get started, go ahead and create a new file in the integration folder called form.spec.js. The name of the file isn’t all that important. We’re prepending "form" because what we’re testing is ultimately a form input. You may want to call it something different depending on how you plan on organizing tests.

We’re going to add a describe block to the file:

describe('Form', () => { beforeEach(() => { cy.visit('/') }) it('it focuses the input', () => { cy.focused().should('have.class', 'form-control') }) })

The beforeEach block is used to avoid unnecessary repetition. For each block of test, we need to visit the application. It would be redundant to repeat that line each time beforeEach ensures Cypress visits the application in each case.

For the test, let’s check that the DOM element in focus when application first loads has a class of form-control. If you check the source file, you will see that the input element has a class called form-control set to it, and we have autoFocus as one of the element attributes:

<input type="text" autoFocus value={this.state.item} onChange={this.handleInputChange} placeholder="Enter a task" className="form-control" />

When you save that, go back to the test screen and select form.spec.js to run the test.

The next thing we’ll do is test whether a user can successfully enter a value into the input field.

it('accepts input', () => { const input = "Learn about Cypress" cy.get('.form-control') .type(input) .should('have.value', input) })

We’ve added some text ("Learn about Cypress") to the input. Then we make use of cy.get to obtain the DOM element with the form-control class name. We could also do something like cy.get('input') and get the same result. After getting the element, cy.type() is used to enter the value we assigned to the input, then we assert that the DOM element with class form-control has a value that matches the value of input.

In other words:

Our application should also have two todos that have been created by default when the app runs. It’s important we have a test that checks that they are indeed listed.

What do we want? In our code, we are making use of the list item (<li>) element to display tasks as items in a list. Since we have two items listed by default, it means that the list should have a length of two at start. So, the test will look something like this:

it('displays list of todo', () => { cy.get('li') .should('have.length', 2) })

Oh! And what would this app be if a user was unable to add a new task to the list? We’d better test that as well.

it('adds a new todo', () => { const input = "Learn about cypress" cy.get('.form-control') .type(input) .type('{enter}') .get('li') .should('have.length', 3) })

This looks similar to what we wrote in the last two tests. We obtain the input and simulate typing a value into it. Then, we simulate submitting a task that should update the state of the application, thereby increasing the length from 2 to 3. So, really, we can build off of what we already have!

Changing the value from three to two will cause the test to fail — that’s what we’d expect because the list should have two tasks by default and submitting once should produce a total of three.

You might be wondering what would happen if the user deletes either (or both) of the default tasks before attempting to submit a new task. Well, we could write a test for that as well, but we’re not making that assumption in this example since we only want to confirm that tasks can be submitted. This is an easy way for us to test the basic submitting functionality as we develop and we can account for advanced/edge cases later.

The last feature we need to test is the deleting tasks. First, we want to delete one of the default task items and then see if there is one remaining once the deletion happens. It’s the same sort of deal as before, but we should expect one item left in the list instead of the three we expected when adding a new task to the list.

it('deletes a todo', () => { cy.get('li') .first() .find('.btn-danger') .click() .get('li') .should('have.length', 1) })

OK, so what happens if we delete both of the default tasks in the list and the list is completely empty? Let’s say we want to display this text when no more items are in the list: "All of your tasks are complete. Nicely done!"

This isn’t too different from what we have done before. You can try it out first then come back to see the code for it.

it.only('deletes all todo', () => { cy.get('li') .first() .find('.btn-danger') .click() .get('li') .first() .find('.btn-danger') .click() .get('.no-task') .should('have.text', 'All of your tasks are complete. Nicely done!') })

Both tests look similar: we get the list item element, target the first one, and make use of cy.find() to look for the DOM element with a btn-danger class name (which, again, is a totally arbitrary class name for the delete button in this example app). We simulate a click event on the element to delete the task item.

I’m checking for "No task!" in this particular test. Testing network requests

Network requests are kind of a big deal because that’s often the source of data used in an application. Say we have a component in our app that makes a request to the server to obtain data which will be displayed to user. Let’s say the component markup looks like this:

class App extends React.Component { state = { isLoading: true, users: [], error: null }; fetchUsers() { fetch(`https://jsonplaceholder.typicode.com/users`) .then(response => response.json()) .then(data => this.setState({ users: data, isLoading: false, }) ) .catch(error => this.setState({ error, isLoading: false })); } componentDidMount() { this.fetchUsers(); } render() { const { isLoading, users, error } = this.state; return ( <React.Fragment> <h1>Random User</h1> {error ? <p>{error.message}</p> : null} {!isLoading ? ( users.map(user => { const { username, name, email } = user; return ( <div key={username}> <p>Name: {name}</p> <p>Email Address: {email}</p> <hr /> </div> ); }) ) : ( <h3>Loading...</h3> )} </React.Fragment> ); } }

Here, we are making use of the JSON Placeholder API as an example. We can have a test like this to test the response we get from the server:

describe('Request', () => { it('displays random users from API', () => { cy.request('https://jsonplaceholder.typicode.com/users') .should((response) => { expect(response.status).to.eq(200) expect(response.body).to.have.length(10) expect(response).to.have.property('headers') expect(response).to.have.property('duration') }) }) })

The benefit of testing the server (as opposed to stubbing it) is that we are certain the response we get is the same as that which a user will get. To learn more about network requests and how you can stub network requests, see this page in the Cypress documentation.

Running tests from the command line

Cypress tests can run from the terminal without the provided UI:

./node_modules/.bin/cypress run

...or

npx cypress run

Let’s run the form tests we wrote:

npx cypress run --record --spec "cypress/integration/form.spec.js"

Terminal should output the results right there with a summary of what was tested.

There’s a lot more about using Cypress with the command line in the documentation.

That’s a wrap!

Tests are something that either gets people excited or scared, depending on who you talk to. Hopefully what we’ve looked at in this post gets everyone excited about implementing tests in an application and shows how relatively straightforward it can be. Cypress is an excellent tool and one I’ve found myself reaching for in my own work, but there are others as well. Regardless of what tool you use (and how you feel about tests), hopefully you see the benefits of testing and are more compelled to give them a try.

Related resources

The post Using Cypress to Write Tests for a React Application appeared first on CSS-Tricks.

Everything You Need to Know About Date in JavaScript

Css Tricks - Tue, 06/11/2019 - 4:27am

Date is weird in JavaScript. It gets on our nerves so much that we reach for libraries (like Date-fns and Moment) the moment (ha!) we need to work with date and time.

But we don't always need to use libraries. Date can actually be quite simple if you know what to watch out for. In this article, I'll walk you through everything you need to know about the Date object.

First, let's acknowledge the existence of timezones.

Timezones

There are hundreds of timezones in our world. In JavaScript, we only care about two—Local Time and Coordinated Universal Time (UTC).

  • Local time refers to the timezone your computer is in.
  • UTC is synonymous with Greenwich Mean Time (GMT) in practice.

By default, almost every date method in JavaScript (except one) gives you a date/time in local time. You only get UTC if you specify UTC.

With this, we can talk about creating dates.

Creating a date

You can create a date with new Date(). There are four possible ways to use new Date():

  1. With a date-string
  2. With date arguments
  3. With a timestamp
  4. With no arguments
The date-string method

In the date-string method, you create a date by passing a date-string into new Date.

new Date('1988-03-21')

We tend towards the date-string method when we write dates. This is natural because we've been using date strings all our lives.

If I write 21-03-1988, you have no problems deducing it's 21st of March, 1988. Yeah? But if you write 21-03-1988 in JavaScript, you get Invalid Date.

new Date('21-03-1988') returns Invalid Date.

There's a good reason for this.

We interpret date strings differently in different parts of the world. For example 11-06-2019 is either 11th June, 2019 or 6th November 2019. But you can't be sure which one I'm referring to, unless you know the date system I'm using.

In JavaScript, if you want to use a date string, you need to use a format that's accepted worldwide. One of these formats is the ISO 8601 Extended format.

// ISO 8601 Extended format `YYYY-MM-DDTHH:mm:ss:sssZ`

Here's what the values mean:

  • YYYY: 4-digit year
  • MM: 2-digit month (where January is 01 and December is 12)
  • DD: 2-digit date (0 to 31)
  • -: Date delimiters
  • T: Indicates the start of time
  • HH: 24-digit hour (0 to 23)
  • mm: Minutes (0 to 59)
  • ss: Seconds (0 to 59)
  • sss: Milliseconds (0 to 999)
  • :: Time delimiters
  • Z: If Z is present, date will be set to UTC. If Z is not present, it'll be Local Time. (This only applies if time is provided.)

Hours, minutes, seconds and milliseconds are optional if you're creating a date. So, if you want to create a date for 11th June 2019, you can write this:

new Date('2019-06-11')

Pay special attention here. There's a huge problem with creating dates with date strings. You can spot the problem if you console.log this date.

If you live in an area that's behind GMT, you'll get a date that says 10th June.

new Date('2019-06-11') produces 10th June if you're in a place behind GMT.

If you live in an area that's ahead of GMT, you'll get a date that says 11th June.

new Date('2019-06-11') produces 11th June if you're in a place after GMT.

This happens because the date-string method has a peculiar behavior: If you create a date (without specifying time), you get a date set in UTC.

In the above scenario, when you write new Date('2019-06-11'), you actually create a date that says 11th June, 2019, 12am UTC. This is why people who live in areas behind GMT get a 10th June instead of 11th June.

If you want to create a date in Local Time with the date-string method, you need to include the time. When you include time, you need to write the HH and mm at a minimum (or Google Chrome returns an invalid date).

new Date('2019-06-11T00:00') Date created in Local Time vsl. Date created in UTC.

The whole Local Time vs. UTC thing with date-strings can be a possible source of error that's hard to catch. So, I recommend you don't create dates with date strings.

(By the way, MDN warns against the date-string approach since browsers may parse date strings differently).

MDN recommends against creating date with date strings.

If you want to create dates, use arguments or timestamps.

Creating dates with arguments

You can pass in up to seven arguments to create a date/time.

  1. Year: 4-digit year.
  2. Month: Month of the year (0-11). Month is zero-indexed. Defaults to 0 if omitted.
  3. Day: Day of the month (1-31). Defaults to 1 if omitted.
  4. Hour: Hour of the day (0-23). Defaults to 0 if omitted.
  5. Minutes: Minutes (0-59). Defaults to 0 if omitted.
  6. Seconds: Seconds (0-59). Defaults to 0 if omitted.
  7. Milliseconds: Milliseconds (0-999). Defaults to 0 if omitted.
// 11th June 2019, 5:23:59am, Local Time new Date(2019, 5, 11, 5, 23, 59)

Many developers (myself included) avoid the the arguments approach because it looks complicated. But it's actually quite simple.

Try reading numbers from left to right. As you go left to right, you insert values in decreasing magnitude: year, month, day, hours, minutes, seconds, and milliseconds.

new Date(2017, 3, 22, 5, 23, 50) // This date can be easily read if you follow the left-right formula. // Year: 2017, // Month: April (because month is zero-indexed) // Date: 22 // Hours: 05 // Minutes: 23 // Seconds: 50

The most problematic part with Date is that the Month value is zero-indexed, as in, January === 0, February === 1, March === 2 and so on.

We have no idea why month in JavaScript is zero-indexed, but it is. Rather than argue about why January should be 1 (and not 0), it's better to accept that month is zero-indexed in JavaScript. Once you accept this fact, dates become much easier to work with.

Here are some more examples for you to familiarize yourself:

// 21st March 1988, 12am, Local Time. new Date(1988, 2, 21) // 25th December 2019, 8am, Local Time. new Date(2019, 11, 25, 8) // 6th November 2023, 2:20am, Local Time new Date(2023, 10, 6, 2, 20) // 11th June 2019, 5:23:59am, Local Time new Date(2019, 5, 11, 5, 23, 59)

Notice dates created with arguments are all in Local Time?

That's one of the perks of using arguments—you won't get confused between Local Time and UTC. If you ever need UTC, you create a date in UTC this way:

// 11th June 2019, 12am, UTC. new Date(Date.UTC(2019, 5, 11)) Creating dates with timestamps

In JavaScript, a timestamp is the amount of milliseconds elapsed since 1 January 1970 (1 January 1970 is also known as Unix epoch time). From my experience, you rarely use timestamps to create dates. You only use timestamps to compare between different dates (more on this later).

// 11th June 2019, 8am (in my Local Time, Singapore) new Date(1560211200000) With no arguments

If you create a date without any arguments, you get a date set to the current time (in Local Time).

new Date() The time now.

You can tell from the image that it's 25th May, 11:10am in Singapore when I wrote this article.

Summary about creating dates
  1. You can create date with new Date().
  2. There are four possible syntaxes:
    1. With a date string
    2. With arguments
    3. With timestamp
    4. With no arguments
  3. Never create a date with the date string method.
  4. It's best to create dates with the arguments method.
  5. Remember (and accept) that month is zero-indexed in JavaScript.

Next, let's talk about converting a date into a readable string.

Formatting a date

Most programming languages give you a formatting tool to create any Date format you want. For example, in PHP, you can write date("d M Y") to a date like 23 Jan 2019.

But there's no easy way to format a date in JavaScript.

The native Date object comes with seven formatting methods. Each of these seven methods give you a specific value (and they're quite useless).

const date = new Date(2019, 0, 23, 17, 23, 42)
  1. toString gives you Wed Jan 23 2019 17:23:42 GMT+0800 (Singapore Standard Time)
  2. toDateString gives you Wed Jan 23 2019
  3. toLocaleString gives you 23/01/2019, 17:23:42
  4. toLocaleDateString gives you 23/01/2019
  5. toGMTString gives you Wed, 23 Jan 2019 09:23:42 GMT
  6. toUTCString gives you Wed, 23 Jan 2019 09:23:42 GMT
  7. toISOString gives you 2019-01-23T09:23:42.079Z

If you need a custom format, you need to create it yourself.

Writing a custom date format

Let's say you want something like Thu, 23 January 2019. To create this value, you need to know (and use) the date methods that comes with the Date object.

To get dates, you can use these four methods:

  1. getFullYear: Gets 4-digit year according to local time
  2. getMonth: Gets month of the year (0-11) according to local time. Month is zero-indexed.
  3. getDate: Gets day of the month (1-31) according to local time.
  4. getDay: Gets day of the week (0-6) according to local time. Day of the week begins with Sunday (0) and ends with Saturday (6).

It's simple to create 23 and 2019 for Thu, 23 January 2019. We can use getFullYear and getDate to get them.

const d = new Date(2019, 0, 23) const year = d.getFullYear() // 2019 const date = d.getDate() // 23

It's harder to get Thu and January.

To get January, you need to create an object that maps the value of all twelve months to their respective names.

const months = { 0: 'January', 1: 'February', 2: 'March', 3: 'April', 4: 'May', 5: 'June', 6: 'July', 7: 'August', 8: 'September', 9: 'October', 10: 'November', 11: 'December' }

Since Month is zero-indexed, we can use an array instead of an object. It produces the same results.

const months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]

To get January, you need to:

  1. Use getMonth to get the zero-indexed month from the date.
  2. Get the month name from months
const monthIndex = d.getMonth() const monthName = months[monthIndex] console.log(monthName) // January

The condensed version:

const monthName = months(d.getMonth()) console.log(monthName) // January

You do the same thing to get Thu. This time, you need an array that contains seven days of the week.

const days = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]

Then you:

  1. Get dayIndex with getDay
  2. Use dayIndex to get dayName
const dayIndex = d.getDay() const dayName = days[dayIndex] // Thu

Short version:

const dayName = days[d.getDay()] // Thu

Then, you combine all the variables you created to get the formatted string.

const formatted = `${dayName}, ${date} ${monthName} ${year}` console.log(formatted) // Thu, 23 January 2019

Yes, it tedious. But it's not impossible once you get the hang of it.

If you ever need to create a custom-formatted time, you can use the following methods:

  1. getHours: Gets hours (0-23) according to local time.
  2. getMinutes: Gets minutes (0-59) according to local time.
  3. getSeconds: Gets seconds (0-59) according to local time.
  4. getMilliseconds: Gets milliseconds (0-999) according to local time.

Next, let's talk about comparing dates.

Comparing dates

If you want to know whether a date comes before or after another date, you can compare them directly with >, <, >= and <=.

const earlier = new Date(2019, 0, 26) const later = new Date(2019, 0, 27) console.log(earlier < later) // true

It's more difficult if you want to check if two dates fall exactly at the same time. You can't compared them with == or ===.

const a = new Date(2019, 0, 26) const b = new Date(2019, 0, 26) console.log(a == b) // false console.log(a === b) // false

To check whether two dates fall exactly at the same time, you can check their timestamps with getTime.

const isSameTime = (a, b) => { return a.getTime() === b.getTime() } const a = new Date(2019, 0, 26) const b = new Date(2019, 0, 26) console.log(isSameTime(a, b)) // true

If you want to check whether two dates fall on the same day, you can check their getFullYear, getMonth and getDate values.

const isSameDay = (a, b) => { return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate()=== b.getDate() } const a = new Date(2019, 0, 26, 10) // 26 Jan 2019, 10am const b = new Date(2019, 0, 26, 12) // 26 Jan 2019, 12pm console.log(isSameDay(a, b)) // true

There's one final thing we have to cover.

Getting a date from another date

There are two possible scenarios where you want to get a date from another date.

  1. Set a specific date/time value from another date.
  2. Add/subtract a delta from another date.
Setting a specific date/time

You can use these methods to set a date/time from another date:

  1. setFullYear: Set 4-digit year in Local Time.
  2. setMonth: Set month of the year in Local Time.
  3. setDate: Set day of the month in Local Time.
  4. setHours: Set hours in Local Time.
  5. setMinutes: Set minutes in Local Time.
  6. setSeconds: Set seconds in Local Time.
  7. setMilliseconds: Set milliseconds in Local Time.

For example, if you want to set a date to the 15th of the month, you can use setDate(15).

const d = new Date(2019, 0, 10) d.setDate(15) console.log(d) // 15 January 2019

If you want to set the month to June, you can use setMonth. (Remember, month in JavaScript is zero-indexed!)

const d = new Date(2019, 0, 10) d.setMonth(5) console.log(d) // 10 June 2019

Note: The setter methods above mutate the original date object. In practice, we should not mutate objects (more on why here). We should perform these operations on a new date object instead.

const d = new Date(2019, 0, 10) const newDate = new Date(d) newDate.setMonth(5) console.log(d) // 10 January 2019 console.log(newDate) // 10 June 2019 Adding/Subtracting delta from another date

A delta is a change. By adding/subtracting delta from another date, I mean this: You want to get a date that's X from another date. It can be X year, X month, X day, etc.

To get a delta, you need to know the current date's value. You can get it using these methods:

  1. getFullYear: Gets 4-digit year according to local time
  2. getMonth: Gets month of the year (0-11) according to local time.
  3. getDate: Gets day of the month (1-31) according to local time.
  4. getHours: Gets hours (0-23) according to local time.
  5. getMinutes: Gets minutes (0-59) according to local time.
  6. getSeconds: Gets seconds (0-59) according to local time.
  7. getMilliseconds: Gets milliseconds (0-999) according to local time.

There are two general approaches to add/subtract a delta. The first approach is more popular on Stack Overflow. It's concise, but harder to grasp. The second approach is more verbose, but easier to understand.

Let's go through both approaches.

Say you want to get a date that's three days from today. For this example, let's also assume today is 28 March 2019. (It's easier to explain when we're working with a fixed date).

The first approach (the set approach) // Assumes today is 28 March 2019 const today = new Date(2019, 2, 28)

First, we create a new Date object (so we don't mutate the original date)

const finalDate = new Date(today)

Next, we need to know the value we want to change. Since we're changing days, we can get the day with getDate.

const currentDate = today.getDate()

We want a date that's three days from today. We'll use add the delta (3) to the current date.

finalDate.setDate(currentDate + 3)

Full code for the set approach:

const today = new Date(2019, 2, 28) const finalDate = new Date(today) finalDate.setDate(today.getDate() + 3) console.log(finalDate) // 31 March 2019 The second approach (the new Date approach)

Here, we use getFullYear, getMonth, getDate and other getter methods until we hit the type of value we want to change. Then, we use create the final date with new Date.

const today = new Date(2019, 2, 28) // Getting required values const year = today.getFullYear() const month = today.getMonh() const day = today.getDate() // Creating a new Date (with the delta) const finalDate = new Date(year, month, day + 3) console.log(finalDate) // 31 March 2019

Both approaches work. Choose one and stick with it.

Automatic date correction

If you provide Date with a value that's outside of its acceptable range, JavaScript recalculates the date for you automatically.

Here's an example. Let's say we set date to 33rd March 2019. (There's no 33rd March on the calendar). In this case, JavaScript adjusts 33rd March to 2nd April automatically.

// 33rd March => 2nd April new Date(2019, 2, 33) 33rd March gets converted to 2nd April automatically.

This means you don't need to worry about calculating minutes, hours, days, months, etc. when creating a delta. JavaScript handles it for you automatically.

// 33rd March => 2nd April new Date(2019, 2, 30 + 3) 30 + 3 = 33. 33rd March gets converted to 2nd April automatically.

And that's everything you need to know about JavaScript's native Date object.

Interested to learn more JavaScript?

If you found this intro to Date useful, you might love Learn JavaScript, a course I created to teach people everything they need to know about JavaScript.

In the course, I cover the basic concepts of what you need to know, then I show you how to use the concepts you learned to build real-world components.

Have a look. You might find it helpful.

In the meantime, if you have any JavaScript questions, feel free to contact me. I'll do by best to create free articles to answer your questions.

The post Everything You Need to Know About Date in JavaScript appeared first on CSS-Tricks.

Level up your .sort game

Css Tricks - Mon, 06/10/2019 - 2:45am

Sorting is a super handy JavaScript method that can display the values of an array in a certain order. Whether that’s real estate listings by price, burger joints by distance, or best nearby happy hours by rating, sorting arrays of information is a common need.

If you’re already doing this with JavaScript on a project, you are will likely using the built-in array .sort method, which is in the same family of array methods that includes .filter, .map and .reduce.

Let's take a look at how to do that!

A quick note about side effects

Before going into the details of how to use .sort, there is a very important detail that needs to be addressed. While many of the ES5 array methods such as .filter, .map, and .reduce will return a new array and leave the original untouched, .sort will sort the array in place. If this is unwanted, an ES6 technique to avoid this is using the spread operator to concisely create a new array.

const foo = ['c','b','a']; const bar = ['x','z','y']; const fooSorted = foo.sort(); const barSorted = [...bar].sort(); console.log({foo, fooSorted, bar, barSorted}); /* { "foo": [ "a", "b", "c" ], "fooSorted": [ "a", "b", "c" ], "bar": [ "x", "z", "y" ], "barSorted": [ "x", "y", "z" ] } */

foo and fooSorted both reference the same array, but bar and barSorted are now individual arrays.

General overview

The only parameter of the .sort method is a function. The spec refers to this as the compareFn — I will refer to it as the "comparison function" for the rest of the post. This comparison function accepts two parameters, which I will refer to as a and b. a and b are the two elements that we will be comparing. If you do not provide a comparison function, the array will coerce each element into a string and sort according to Unicode points.

If you would like the a to be ordered first in the array, the comparison function should return a negative integer; for b, a positive integer. If you would like the two to maintain their current order, return a 0.

If you don't understand, don't worry! Hopefully it will become much more clear with a few examples.

Comparing numbers

One of the simplest callbacks to write is a number comparison.

const numbers = [13,8,2,21,5,1,3,1]; const byValue = (a,b) => a - b; const sorted = [...numbers].sort(byValue); console.log(sorted); // [1,1,2,3,5,8,13,21]

If a is greater than b, a - b will return a positive number, so b will be sorted first.

Comparing strings

When comparing strings, the > and < operators will compare values based on each string’s Unicode value. This means that all uppercase letters will be “less” than all lowercase letters, which can lead to unexpected behavior.

JavaScript does have a method to help with comparing strings: the String.prototype.localeCompare method. This method accepts a comparison string, a locale, and an options object. The options object accepts a few properties (all of which you can view here), but I find that the most useful is "sensitivity." This will affect how comparisons work between letter variations such as case and accent.

const strings = ['Über', 'alpha', 'Zeal', 'über', 'uber', 'Uber', 'Alpha', 'zeal']; const sortBySensitivity = sensitivity => (a, b) => a.localeCompare( b, undefined, // locale string -- undefined means to use browser default { sensitivity } ); const byAccent = sortBySensitivity('accent'); const byBase = sortBySensitivity('base'); const byCase = sortBySensitivity('case'); const byVariant = sortBySensitivity('variant'); // default const accentSorted = [...strings].sort(byAccent); const baseSorted = [...strings].sort(byBase); const caseSorted = [...strings].sort(byCase); const variantSorted = [...strings].sort(byVariant); console.log({accentSorted, baseSorted, caseSorted, variantSorted}); /* { "accentSorted": [ "alpha", "Alpha", "uber", "Uber", "Über", "über", "Zeal", "zeal" ], "baseSorted": [ "alpha", "Alpha", "Über", "über", "uber", "Uber", "Zeal", "zeal" ], "caseSorted": [ "alpha", "Alpha", "über", "uber", "Über", "Uber", "zeal", "Zeal" ], "variantSorted": [ "alpha", "Alpha", "uber", "Uber", "über", "Über", "zeal", "Zeal" ] } */

To me, baseSorted seems to be the most logical for most alphabetical sorting — ‘ü’, ‘u’, ‘Ü’, and ‘U’ are equivalent, so they remain in the order of the original array.

Running functions before comparing values

You may want to run a comparison function on a value that is derived from each array’s element. First, let’s write a comparison function factory that will "map" over the element before calling the comparison function.

const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));

One use case for this is sorting based on the attribute of an object.

const purchases = [ { name: 'Popcorn', price: 5.75 }, { name: 'Movie Ticket', price: 12 }, { name: 'Soda', price: 3.75 }, { name: 'Candy', price: 5 }, ]; const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b)); const byValue = (a,b) => a - b; const toPrice = e => e.price; const byPrice = sortByMapped(toPrice,byValue); console.log([...purchases].sort(byPrice)); /* [ { name: "Soda", price: 3.75 }, { name: "Candy", price: 5 }, { name: "Popcorn", price: 5.75 }, { name: "Movie Ticket", price: 12 } ] */

Another case might be to compare an array of dates.

const dates = ['2018-12-10', '1991-02-10', '2015-10-07', '1990-01-11']; const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b)); const toDate = e => new Date(e).getTime(); const byValue = (a,b) => a - b; const byDate = sortByMapped(toDate,byValue); console.log([...dates].sort(byDate)); // ["1990-01-11", "1991-02-10", "2015-10-07", "2018-12-10"] Reversing a sort

There are some cases where you may want to reverse the outcome of a comparison function. This is subtly different than doing a sort and then reversing the result in the way ties are handled: if you reverse the outcome, ties will also be reversed in order.

To write a higher order function that accepts a comparison function and returns a new one, you will need to flip the sign of the comparison’s return value.

const flipComparison = fn => (a,b) => -fn(a,b); const byAlpha = (a,b) => a.localeCompare(b, null, { sensitivity: 'base' }); const byReverseAlpha = flipComparison(byAlpha); console.log(['A', 'B', 'C'].sort(byReverseAlpha)); // ['C','B','A'] Running a tiebreaker sort

There are times when you may want to have a "tie-breaker" sort — that is, another comparison function that is used in the case of a tie.

By using [].reduce, you can flatten an array of comparison functions into a single one.

const sortByMapped = map => compareFn => (a,b) => compareFn(map(a),map(b)); const flipComparison = fn => (a,b) => -fn(a,b); const byValue = (a,b) => a - b; const byPrice = sortByMapped(e => e.price)(byValue); const byRating = sortByMapped(e => e.rating)(flipComparison(byValue)); const sortByFlattened = fns => (a,b) => fns.reduce((acc, fn) => acc || fn(a,b), 0); const byPriceRating = sortByFlattened([byPrice,byRating]); const restaurants = [ { name: "Foo's Burger Stand", price: 1, rating: 3 }, { name: "The Tapas Bar", price: 3, rating: 4 }, { name: "Baz Pizza", price: 3, rating: 2 }, { name: "Amazing Deal", price: 1, rating: 5 }, { name: "Overpriced", price: 5, rating: 1 }, ]; console.log(restaurants.sort(byPriceRating)); /* {name: "Amazing Deal", price: 1, rating: 5} {name: "Foo's Burger Stand", price: 1, rating: 3} {name: "The Tapas Bar", price: 3, rating: 4} {name: "Baz Pizza", price: 3, rating: 2} {name: "Overpriced", price: 5, rating: 1} */ Writing a random sort

You might want to sort an array "randomly." One technique that I have seen is to use the following function as the comparison function.

const byRandom = () => Math.random() - .5;

Since Math.random() returns a "random" number between 0 and 1, the byRandom function should return a positive number half of the time and a negative number the other half. This seems like it would be a good solution, but unfortunately, since the comparison function is not "consistent" — meaning it may not return the same value when called multiple times with the same values — it may result in some unexpected results.

For example, let's take an array of numbers between 0 and 4. If this byRandom function was truly random, it would be expected that the new index of each number would be spread out equally over enough iterations. The original 0 value would be just as likely to be in index 4 as index 0 in the new array. However, in practice, this function will bias each number to its original position.

See the Pen
Array.sort() Random &#x1f44e;
by Adam Giese (@AdamGiese)
on CodePen.

The "diagonal" from the top-left will statistically have the greatest value. In an ideal and truly random sort, each table cell would hover around 20%.

The fix for this is to find a way to ensure that the comparison function remains consistent. One way to do this is to map the random value to each array element before the comparison, then map it away after.

const sortByMapped = map => compareFn => (a,b) => compareFn(map(a),map(b)); const values = [0,1,2,3,4,5,6,7,8,9]; const withRandom = (e) => ({ random: Math.random(), original: e }); const toOriginal = ({original}) => original; const toRandom = ({random}) => random; const byValue = (a,b) => a - b; const byRandom = sortByMapped(toRandom)(byValue); const shuffleArray = array => array .map(withRandom) .sort(byRandom) .map(toOriginal);

This ensures that each element has a single random value that is only calculated once per element rather than once per comparison. This removes the sorting bias towards the original position.

See the Pen
Array.sort() Random &#x1f44d;
by Adam Giese (@AdamGiese)
on CodePen.

The post Level up your .sort game appeared first on CSS-Tricks.

Designing with Motifs

Css Tricks - Mon, 06/10/2019 - 2:43am

I love the way Erik Kennedy talks about digital design. Very practical and understandable. Have a listen to a chat with him we had on ShopTalk.

One of his latest blog posts is titled "The #1 Way to Spice Up Your Designs (And Create a More Cohesive Brand)" and it's about something he pegs as more of an intermediate (beyond the basics) level design tip about the idea of motifs.

In music, that might be a bit of a melody that asserts itself periodically and kinda informs the rest of the song. It's equally interesting in design, where a theme — perhaps a geometric element — is sprinkled in tastefully that helps the gestalt. Ties the room together, as they say.

Anyway, if you're serious about getting better at design, his course is where it's at and opens up in mid-June. So, now's the time to think about it.

Direct Link to ArticlePermalink

The post Designing with Motifs appeared first on CSS-Tricks.

Using DevTools to Improve the UX Design to Development Process

Css Tricks - Fri, 06/07/2019 - 8:31am

I’d like to tell you how I see code and design intersect and support one another. Specifically, I want to cover how designers can use code in their everyday work. I suggest this not because it’s a required skill, but because even a baseline understanding of coding can make designs better and the hand-off from design to development smoother.

As a UX Designer, I am always looking for good ways to both explore my UX design problems and communicate the final designs to others. Over the past 30 years, my work has always involved working alongside developers, but generally there has been a great divide between what I do and what developers do.

I can code at a basic level. For example, I’ve helped teach C to undergraduates back when I was a post-graduate student. I’ve worked on the usability of JDeveloper Oracle’s Integrated Development Environment (IDE) for Java. I also worked for a very short while on simplifying the UX of a WordPress content management environment to make it accessible to less technical users. This required a good understanding of HTML and CSS. I also volunteered on the design of the PHP website and had to develop some understanding of the server side of web development.

But even given these experiences, I am not a developer in any true sense of the word. If I happen to be looking at code, it’s in a “just in time” learning model — I look up what I need and then hack it until it works. Learning this way has often been frowned upon, a bit like learning to drive without lessons. You pick up bad development habits but maybe that's OK for the work I do.

So, no I don’t develop or write code. My day-to-day work is mostly been spent drawing, talking and gathering requirements. As far as design goes, I’ll start by sketching concepts in a notebook or using Balsamiq. Then I draw up UX wireframes and prototypes using tools like Axure, Adobe XD, InVision Studio, Figma and Sketch. By the time I'm ready to hand off my deliverables to development, all the visual assets and documentation have been defined and communicated. But I don’t step over the line into code development. That is just not my area of expertise.

So, why should designers know code?

We’ve already established that I’m no developer, but I have recently become an advocate for designers getting a good feel for how design and code interact.

In fact, I’d call it “playing with code.” I am definitely not suggesting that UX designers become developers, but at the very least, I think designers would benefit by becoming comfortable with a basic understanding of what is currently possible with CSS and best practices in HTML.

Being experimental is a huge part of doing design. Code is just another medium with which we can experiment and build beautiful solutions. So, we're going to look at a couple of ways designers can experiment with code, even with a light understanding of it. What we're covering here may be obvious to developers, but there are plenty of designers out there who have never experimented with code and will be seeing these for the first time.

So, it's for them (and maybe a refresher for you) that we look at the following browser tools.

DevTools: The ultimate code playground

One of the concerns a UX designer might have is knowing how a design holds up once it’s in the browser. Are the colors accurate? Are fonts legible throughout? How do the elements respond on various devices? Will my grey hover state work with the white/grey zebra striping on my application grids in practice? These are some of the styling and interaction issues designers are thinking about when we hand our work off for development.

This is where DevTools can be a designer’s best friend. Every browser has its own version of it. You may have already played with such tools before. It’s that little “Inspect” option when right clicking on the screen.

Entering the wonderful world of DevTools can be done from any webpage.

What makes DevTools such a wonderful resource is that it provides a way to manipulate the code of a live website or web application without having to set up a development environment. And it’s disposable. Any edits you make are for your eyes only and are washed away the very moment the browser refreshes.

Editing code in DevTools makes changes to the page on the fly.

Further, DevTools can mimic other devices.

Need to see how a page or changes to it look on other devices? DevTools can give you an idea.

And, if you haven’t seen it yet, Firefox released a wonderful new shape path editor that's very valuable for exploring interesting designs.

Over the past few months, I have been working on a complex web client for an enterprise-level application. Last sprint, my UX design story was to explore the look of the entry page of the web application and how to introduce a new color scheme. It was hard to envision how the changes I was making were going to impact the tool as a whole as some of the components I was changing are used throughout the product.

One day, when discussing a design decision, one of the developers tested out my suggested change to a component using the latest DevTools in his browser. I was amazed by how much DevTools has grown and expanded since I last remember it. I could immediately see the impact of that change across our whole web application and how different design decisions interacted with the existing design. I started to experiment with DevTools myself and was able to preview and experiment with how my own simple CSS changes to components would impact the whole web application. Super helpful!

However, it was also a little frustrating to not be able store my experiments and changes for future reference. So, I went exploring to see what else was out there to support my design process.

Chrome browser extensions

DevTools is are amazing right out of the box, but experimenting with code gets even more awesome when browser extensions are added to the mix. Chrome, in particular, has a couple that I really like.

Chrome Extension 1: User CSS

User CSS is a Chrome browser extension that allows you to save the changes you make in DevTools in an editable CSS code tab. These CSS changes are automatically executed on that page if User CSS is enabled. This means that you can set up CSS overrides for any page on the web, view them later, and share them with others. This can be an incredible tool when, say, doing a design review of a staging site prior to release, or really any design exploration for a web application or website that is viewable in a browser.

The first thing I do with User CSS is make the changes in the Chrome elements panel. Then, I simply cut and paste the CSS changes from Chrome’s DevTools to the User CSS code tab as I am going along. This video shows in detail the different ways to edit CSS, HTML and Javascript in Chrome DevTools and how I use UserCSS.

User CSS has a nice built-in code editor, so my code is always well formatted and includes syntax highlighting so I don't have to worry about that sort of thing. I particularly like the fact that overrides are executed immediately so you can see changes on the fly. It also has a useful switch that allows you to turn your overrides on and off. This makes it very simple to demonstrate a set of changes to a team. This extension has allowed me to easily present a comparison between an existing page design and proposed changes. I’ve even used it to make a simple video demonstrating the proposed design changes.

In this video I make some simple edits to my web page and then show how I can turn on and off the edits by simply clicking the on/off button on User CSS:

This extension is a perfect if you all you need to do is edit CSS, particularly if you have some very simple design changes to make want to those changes to persist. However, the complexity of a design increases, I have found myself wanting to save more than one snippet of code at a time. Copying and pasting code in and out of the User CSS editor was becoming a pain. I wanted something with more flexibility and freedom to experiment. I also wanted to be able to look at simple changes to the HTML of my web application and even play with a bit of JavaScript.

That's where the next extension comes into play.

Chrome Extension 2: Web Overrides

The second Chrome extension I found is called Web Override and it provides a way to override HTML, CSS and JavaScript. All of them! This is presented as three tabs, much the same way CodePen does, which makes it a very powerful tool for creating rough working design prototypes.

Web Overrides also allows you to save multiple files so that you can switch different parts of a design on or off in different combinations. It also quickly switches between the different options to show off different design concepts.

This video shows how I added an HTML element into a page and edited the new element with some basic CSS:

Using the HTML tab makes it possible to edit any element on the page, like swap out a logo, remove unnecessary elements, or add new ones. The JavaScript tab is similar in that I can do simple changes, like inject additional text into the website title so that I can test how dynamic changes might affect the layout — this can be useful for testing different scenarios, such as differences with internationalization.

These edits may be trivial from a coding perspective, but they allow me to explore hundreds of alternative designs in a much shorter time and with a lot less risk than scooting pixels around in a design application. I literally could not explore as many ideas as quickly using my traditional UX prototyping tools as I can with this one extension.

And, what is more, both me and my team have confidence in the design deliverables because we tested them early on in the browser. Even the most pixel-perfect Photoshop file can get lost in translation when the design is in the browser because it's really just a snapshot of a design in a static state. Testing designs first in the browser using these extensions prove that what we have designed is possible.

On the flip side of this, you might want to check out how Jon Kantner used similar browser extensions to disable CSS as a means to audit the semantic markup various sites. It's not exactly design-related, but interesting to see how these tools can have different use cases.

What I’ve learned so far

I am excited about what I have learned since leaning into DevTools and browser extensions. I believe my designs are so much better as a result. I also find myself able to have more productive conversations with developers because we now have a way to communicate well. The common ground between design and code in rapid prototypes really helps facilitate discussion. And, because I am playing around with actual code, I have a much better sense about how the underlying code will eventually be written and can empathize a lot more with the work developers do — and perhaps how I can make their jobs easier in the process.

It has also created a culture of collaborative rapid prototyping on my team which is a whole other story.

Playing with code has opened up new ideas and encouraged me to adapt my work to the context of the web. It’s been said that getting into the browser earlier in the design process is ideal and these are the types of tools that allow me (and you) to do just that!

Do you have other tools or processes that you use to facilitate the collaboration between design and code? Please share them in the comments!

The post Using DevTools to Improve the UX Design to Development Process appeared first on CSS-Tricks.

Weekly Platform News: Feature Policy, ECMAScript i18n API, Packaged PWAs

Css Tricks - Fri, 06/07/2019 - 4:27am

Šime posts regular content for web developers on webplatform.news.

New Feature Policy API in Chrome

Pete LePage: You can use the document.featurePolicy.allowedFeatures method in Chrome to get a list of all Feature Policy-controlled features that are allowed on the current page.

This API can be useful when implementing a feature policy (and updating an existing feature policy) on your website.

  1. Open your site in Chrome and run the API in the JavaScript console to check which Feature Policy-controlled features are allowed on your site.
  2. Read about individual features on featurepolicy.info and decide which features should be disabled ('none' value), and which features should be disabled only in cross-origin <iframe> elements ('self' value).
  3. Add the Feature-Policy header to your site’s HTTP responses (policies are separated by semicolons).
  4. Feature-Policy: geolocation 'self';sync-xhr 'none'
  5. Repeat Step 1 to confirm that your new feature policy is in effect. You can also scan your site on securityheaders.com.
In other news...
  • Dave Camp: Firefox now blocks cookies from known trackers by default (when the cookie is used in a third-party context). This change is currently in effect only for new Firefox users; existing users will be automatically updated to the new policy "in the coming months."
  • Pete LePage: Chrome for Android now allows websites to share images (and other file types) via the navigator.share method. See Web Platform News Issue 1014 for more information about the Web Share API. Ayooluwa Isaiah's post from yesterday is also a good reference on how to use it.
  • Valerie Young: The ECMAScript Internationalization APIs for date and time formatting (Intl.DateTimeFormat constructor), and number formatting (Intl.NumberFormat constructor) are widely supported in browsers.
  • Alan Jeffrey: Patrick Walton from Mozilla is working on a vector graphics renderer that can render text smoothly at all angles when viewed with an Augmented Reality (AR) headset. We plan to use it in our browsers for AR headsets (Firefox Reality).
  • Pinterest Engineering: Our progressive web app is now available as a standalone desktop application on Windows 10. It can be installed via the Microsoft Store, which "treats the packaged PWA as a first class citizen with access to Windows 10 feature APIs."
  • Jonathan Davis: The flow-root value for the CSS display property has landed in Safari Technology Preview. This value is already supported in Chrome and Firefox. See Web Platform News Issue 871 for a use case.

The post Weekly Platform News: Feature Policy, ECMAScript i18n API, Packaged PWAs appeared first on CSS-Tricks.

Your first performance budget with Lighthouse

Css Tricks - Fri, 06/07/2019 - 4:26am

Ire Aderinokun writes about a new way to set a performance budget (and stick to it) with Lighthouse, Google’s suite of tools that help developers see how performant and accessible their websites are:

Until recently, I also hadn't setup an official performance budget and enforced it. This isn’t to say that I never did performance audits. I frequently use tools like PageSpeed Insights and take the feedback to make improvements. But what I had never done was set a list of metrics that I needed the site to meet, and enforce them using some automated tool.

The reasons for this were a combination of not knowing what exact numbers I should use for budgets as well as there being a disconnect between setting a budget and testing/enforcing it. This is why I was really excited when, at Google I/O this year, the Lighthouse team announced support for performance budgets that can be integrated with Lighthouse. We can now define a simple performance budget in a JSON file, which will be tested as part of the lighthouse audit!

I completely agree with Ire, and much in the same way I’ve tended to neglect sticking to a performance budget simply because the process of testing was so manual and tedious. But no more! As Ire shows in this post, you can even set Lighthouse up to test your budget with every PR in GitHub. That tool is called lighthousebot and it’s just what I’ve been looking for – an automated and predictable way to integrate a performance budget into every change that I make to a codebase.

Today lighthousebot will comment on your PR after a test is complete and it will show you the before and after score:

How neat is that? This reminds me of Gareth Clubb’s recent post about improving web performance and building a culture around budgets in an organization. What better way to remind everyone about performance than right in GitHub after each and every change that they make?

Direct Link to ArticlePermalink

The post Your first performance budget with Lighthouse appeared first on CSS-Tricks.

What if we got aspect-ratio sized images by doing almost nothing?

Css Tricks - Thu, 06/06/2019 - 12:00pm

Say you have an image you're using in an <img> that is 800x600 pixels. Will it actually display as 800px wide on your site? It's very likely that it will not. We tend to put images into flexible container elements, and the image inside is set to width: 100%;. So perhaps that image ends up as 721px wide, or 381px wide, or whatever. What doesn't change is that image's aspect ratio, lest you squish it awkwardly (ignoring the special use-case object-fit scenario).

The main point is that we don't know how much vertical space an image is going to occupy until that image loads. This is the cause of jank! Terrible jank! It's everywhere and it's awful.

There are ways to create aspect-ratio sized boxes in HTML/CSS today. None of the options are particularly elegant because they rely on the "hack" of setting a zero height and pushing the boxes height with padding. Wouldn't it be nicer to have a platform feature to help us here? The first crack at fixing this problem that I know about is an intrinsicsize attribute. Eric Portis wrote about how this works wonderfully in Jank-Free Image Loads.

We'd get this:

<img src="image.jpg" intrinsicsize="800x600" />

This is currently behind a flag in Chrome 71+, and it really does help solve this problem.

But...

The intrinsicsize property is brand new. It will only help on sites where the developers know about it and take the care to implement it. And it's tricky! Images tend to be sized arbitrarily, and the intrinsicsize attribute will need to be custom on every image to be accurate and do its job. That is, if it makes it out of standards at all.

There is another possibility! Eric also talked about the aspect-ratio property in CSS as a potential solution. It's also still just a draft spec. You might say, but how is this helpful? It needs to be just as bespoke as intrinsicsize does, meaning you'd have to do it as inline styles to be helpful. Maybe that's not so bad if it solves a big problem, but inline styles are such a pain to override and it seems like the HTML attribute approach is more inline with the spirit of images. Think of how srcset is a hint to browsers for what images are available to download, allowing the browser to pick the best one for the scenario. Telling the browser about the aspect-ratio upfront is similarly useful.

I heard from Jen Simmons about an absolutely fantastic way to handle this: put a default aspect ratio into the UA stylesheet based on the elements existing width and height attributes. Like this:

img, video { aspect-ratio: attr(width) / attr(height); }

Let that soak in.

Now if you already have:

<img src="image.jpg" width="800" height="600" />

It automatically has the correct aspect ratio as the page loads. That's awesome.

  1. It's easy to understand.
  2. A ton of the internet already has these attributes sitting on their images.
  3. New developers will have no trouble understanding this, and old developers will be grateful there is little (if any) work to do here.

I like the idea of the CSS feature. But I like 100 times more the idea of putting it into the UAUA stylesheet is no small thing to consider — and I'm not qualified to understand all the implications of that — but it feels like a very awesome thing at first consideration.

Jen has a ticket open for people to voice their thoughts and links to the bug ticket where Firefox is going to test this out to see how it goes.

The post What if we got aspect-ratio sized images by doing almost nothing? appeared first on CSS-Tricks.

How to Use the Web Share API

Css Tricks - Thu, 06/06/2019 - 4:21am

The Web Share API is one that has seemingly gone under the radar since it was first introduced in Chrome 61 for Android. In essence, it provides a way to trigger the native share dialog of a device (or desktop, if using Safari) when sharing content — say a link or a contact card — directly from a website or web application.

While it’s already possible for a user to share content from a webpage via native means, they have to locate the option in the browser menu, and even then, there’s no control over what gets shared. The introduction of this API allows developers to add sharing functionality into apps or websites by taking advantage of the native content sharing capabilities on a user’s device.

iOS offers a number of native sharing options.

This approach provides a number of advantages over conventional methods:

  • The user is presented with a wide range of options for sharing content compared to the limited number you might have in your DIY implementation.
  • You can improve your page load times by doing away with third-party scripts from individual social platforms.
  • You don’t need to add a series of buttons for different social media sites and email. A single button is sufficient to trigger the device’s native sharing options.
  • Users can customize their preferred share targets on their own device instead of being limited to just the predefined options.
A note on browser support

Before we get into the details of how the API works, let’s get the issue of browser support out of the way. To be honest, browser support isn’t great at this time. It’s only available for Chrome for Android, and Safari (desktop and iOS).

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafariNoNoNoNoNo12.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox12.2NoNoNo74No

But don’t let that discourage you from adopting this API on your website. It’s pretty easy to implement a fallback for supporting browsers that don’t offer support for it, as you’ll see.

A few requirements for using it

Before you can adopt this API on your own web project, there are two major things to note:

  • Your website has to be served over HTTPS. To facilitate local development, the API also works when your site is running over localhost.
  • To prevent abuse, the API can only be triggered in response to some user action (such as a click event).
Here's an example

To demonstrate how to use this API, I’ve prepared a demo that works essentially the same as it does on my site. Here’s how it looks like:

See the Pen
WebShare API Demo - Start
by Ayooluwa (@ayoisaiah)
on CodePen.

At this moment, once you click the share button, a dialog pops out and shows a few options for sharing the content. Here’s the part of the code that helps us achieve that:

shareButton.addEventListener('click', event => { shareDialog.classList.add('is-open'); });

Let’s go ahead and convert this example to use the Web Share API instead. The first thing to do is check if the API is indeed supported on the user’s browser as shown below:

if (navigator.share) { // Web Share API is supported } else { // Fallback }

Using the Web Share API is as simple as calling the navigator.share() method and passing an object that contains at least one of the following fields:

  • url: A string representing the URL to be shared. This will usually be the document URL, but it doesn’t have to be. You share any URL via the Web Share API.
  • title: A string representing the title to be shared, usually document.title.
  • text: Any text you want to include.

Here’s how that looks in practice:

shareButton.addEventListener('click', event => { if (navigator.share) { navigator.share({ title: 'WebShare API Demo', url: 'https://codepen.io/ayoisaiah/pen/YbNazJ' }).then(() => { console.log('Thanks for sharing!'); }) .catch(console.error); } else { // fallback } });

At this point, once the share button is clicked in a supported browser, the native picker will pop out with all the possible targets that the user can share the data with. Targets can be social media apps, email, instant messaging, SMS or other registered share targets.

The API is promised-based, so you can attach a .then() method to perhaps display a success message if the share was successful, and handle errors with .catch(). In a real-world scenario, you might want to grab the page’s title and URL using this snippet:

const title = document.title; const url = document.querySelector('link[rel=canonical]') ? document.querySelector('link[rel=canonical]').href : document.location.href;

For the URL, we first check if the page has a canonical URL and, if so, use that. Otherwise, we grab the href off document.location.

Providing a fallback is a good idea

In browsers where the Web Share API isn’t supported, we need to provide a fallback mechanism so that users on those browsers still get some sharing options.

In our case, we have a dialog that pops out with a few options for sharing the content and the buttons in our demo do not actually link to anywhere since, well, it’s a demo. But if you want to learn about how you can create your own links to share web pages without third-party scripts, Adam Coti's article is a good place to start.

What we want to do is display the fallback dialog for users on browsers without support for the Web Share API. This is as simple as moving the code that opens the share dialog into the else block:

shareButton.addEventListener('click', event => { if (navigator.share) { navigator.share({ title: 'WebShare API Demo', url: 'https://codepen.io/ayoisaiah/pen/YbNazJ' }).then(() => { console.log('Thanks for sharing!'); }) .catch(console.error); } else { shareDialog.classList.add('is-open'); } });

Now, all users are covered regardless of what browser they’re on. Here's a comparison of how the share button behaves on two mobile browsers, one with Web Share API support, and the other without:

Try it out! Use a browser that supports Web Share, and one that doesn't. It should work similarly to the above demonstration.

See the Pen
WebShare API Demo - End
by Ayooluwa (@ayoisaiah)
on CodePen.

Wrapping up

This covers pretty much the baseline for what you need to know about the Web Share API. By implementing it on your website, visitors can share your content more easily across a wider variety of social networks, with contacts and other native apps.

It’s also worth noting that you’re able to add your web application as a share target if it meets the Progressive Web App installation criteria and is added to a user’s home screen. This a feature of the Web Share Target API which you can read about at Google Developers.

Although browser support is spotty, a fallback is easily implemented, so I see no reason why more websites shouldn’t adopt this. If you want to learn more about this API, you can read the specification here.

Have you used the Web Share API? Please share it in the comments.

The post How to Use the Web Share API appeared first on CSS-Tricks.

Snag Resources from An Event Apart Boston 2019 and Save on Washington D.C. Registration

Css Tricks - Thu, 06/06/2019 - 4:10am

(This is a sponsored post.)

Hey, so we talked a little bit about An Event Apart Boston 2019 leading up to the event and now there are a ton of resources available from it. I stopped counting the number of links after 50 because there's way more than that. Seriously, there's stuff in there on subgrid, working with CSS Regions, design systems, using prefers-reduced-motion... and much, much more, so check it out.

And, while you're at it, you should consider attending the next installment of An Event Apart. It takes place July 29-31 in Washington D.C. and seating — as you might expect — is limited. Like Boston, you can expect to get a treasure trove of useful information, educational content, and valuable training on topics that will help you sharpen your front-end chops and grow your career. Plus, the best part is getting to meet the rest of the great folks at the event — that's where your network grows and real conversations take place.

Register Today

Can't make it to Washington D.C.? No worries, because An Event Apart is also slated to take place in Chicago (August 26-28), Denver (October 28-30) and San Francisco (December 9-11). Now's the time to start planning your trip and begging your boss for a well-deserved self-investment in leveling up.

And if you're wondering whether we have a discount code for you... of course we do! Enter the AEACP at checkout to knock $100 off the price. &#x1f911;

Direct Link to ArticlePermalink

The post Snag Resources from An Event Apart Boston 2019 and Save on Washington D.C. Registration appeared first on CSS-Tricks.

A Course About CSS Layout and Animations

Css Tricks - Wed, 06/05/2019 - 1:17pm

Christina Gorton just released a new course called CSS Layout and Animations as a part of Design+Code, which is a $9/month. That includes a ton of video training on everything from stuff like this to React to Sketch to iOS development... and beyond!

Christina approaches the course with my favorite way to learn this stuff: by starting from a lovely design and then pulling it off with code.

That's Figma as the design tool, which is another tool I love.

Of course, what I really love is that:

  • The course is full of CSS trickery and modern HTML & CSS features, like using flexbox and grid in practical ways.
  • She uses CodePen to prototype everything — the perfect place to get started with a project like this, in my humble opinion.

Direct Link to ArticlePermalink

The post A Course About CSS Layout and Animations appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.