Snippets

Fixed and sticky headers and in-page anchors

I made a little tweak to The Session today. The navigation bar across the top is “sticky” now—it doesn’t scroll with the rest of the content.

I made sure that the stickiness only kicks in if the screen is both wide and tall enough to warrant it. Vertical media queries are your friend!

But it’s not enough to just put some position: fixed CSS inside a media query. There are some knock-on effects that I needed to mitigate.

I use the space bar to paginate through long pages. It drives me nuts when sites with sticky headers don’t accommodate this. I made use of Tim Murtaugh’s sticky pagination fixer. It makes sure that page-jumping with the keyboard (using the space bar or page down) still works. I remember when I linked to this script two years ago, thinking “I bet this will come in handy one day.” Past me was right!

The other “gotcha!” with having a sticky header is making sure that in-page anchors still work. Nicolas Gallagher covers the options for this in a post called Jump links and viewport positioning. Here’s the CSS I ended up using:

Code language: CSS

:target:before {
    content: '';
    display: block;
    height: 3em;
    margin: -3em 0 0;
}

I also needed to check any of my existing JavaScript to see if I was using scrollTo anywhere, and adjust the calculations to account for the newly-sticky header.

Anyway, just a few things to consider if you’re going to make a navigational element “sticky”:

  1. Use min-height in your media query,
  2. Take care of keyboard-initiated page scrolling,
  3. Adjust the positioning of in-page links.

Interaction Media Features

While it’s still true that You Can’t Detect A Touchscreen, the Interaction Media Features media queries can come in handy in edge cases. Still, don’t assume too much about a device, as both the link above and the source for this emphasize.

Thanks to the W3C CSS Working Group and the CSS community, we have a cleaner solution.

On the Media Queries Level 4 Working Draft, there is a spec for Interaction Media Features that includes three definitions:

These provide the capability to query a document based on the presence and accuracy of the user’s pointing device and whether it has the ability to hover over elements.

Let’s take a closer look at each one:

Pointing Device Quality: The pointer Feature

The pointer media feature is used to query about the presence and accuracy of a pointing device such as a mouse. If a device has multiple input mechanisms, the pointer media feature must reflect the characteristics of the “primary” input mechanism, as determined by the user agent.” - W3C

The key word here is “accuracy” of the pointing device.

  • A mouse or a drawing stylus is very accurate and defines the value of fine.
  • A finger or a Kinect peripheral isn’t, and takes the value of coarse.

Therefore, we can adapt our UI elements to the user’s pointer capabilities. This is useful for making hit areas larger, if the user’s main input mechanism is a finger.

Code language: CSS

/* The primary input mechanism of the device includes a pointing device of limited accuracy. */
@media (pointer: coarse) { ... }
 
/* The primary input mechanism of the device includes an accurate pointing device. */
@media (pointer: fine) { ... }
 
/* The primary input mechanism of the device does not include a pointing device. */
@media (pointer: none) { ... }

An example use case for this query is to size the click area of a checkbox or radio.

Hover Capability: The hover Feature

The hover media feature is used to query the user’s ability to hover over elements on the page. If a device has multiple input mechanisms, the hover media feature must reflect the characteristics of the “primary” input mechanism, as determined by the user agent.” - W3C

It’s important to notice that it only evaluates the primary input mechanism. If the primary input mechanism is not able to hover, but the secondary input can, then the query will resolve to none:

For example, a touchscreen where a long press is treated as hovering would match hover: none.” - W3C

  • A touch screen device, where the primary pointer system is the finger and can’t hover, will take the value of none.
  • A device where the primary input is a mouse and can easily hover parts of the page takes the value of hover.

Code language: CSS

/* Primary input mechanism system can 
   hover over elements with ease */
@media (hover: hover) { ... }
 
/* Primary input mechanism cannot hover 
   at all or cannot conveniently hover 
   (e.g., many mobile devices emulate hovering
   when the user performs an inconvenient long tap), 
   or there is no primary pointing input mechanism */
@media (hover: none) { ... }

A good use of this query is a drop-down menu.

Rare Interaction Capabilities: The any-pointer and any-hover Features

On devices that are both touch and have a mouse or a stylus, like the Microsoft Surface, the hover and pointer media query will evaluate the primary input mechanism only.

As Andrea Giammarc pointed out, his Dell XPS 13” touch takes the value of fine, even though it does have a touch screen because the primary input mechanism is a mouse.

[…]

If we want a device like that to take the value of coarse or hover, we can use the Rare Interaction Capabilities.

The any-pointer and any-hover media features are identical to the pointer and hover media features, but they correspond to the union of capabilities of all the pointing devices available to the user. More than one of their values can match, if different pointing devices have different characteristics. They must only match none if all of the pointing devices would match none for the corresponding query, or there are no pointing devices at all.” - W3C

Code language: CSS

/* One or more available input mechanism(s) 
   can hover over elements with ease */
@media (any-hover: hover) { ... }
 
/* One or more available input mechanism(s) can hover, 
   but not easily (e.g., many mobile devices emulate 
   hovering when the user performs a long tap) */
@media (any-hover: on-demand) { ... }
 
/* One or more available input mechanism(s) cannot 
   hover (or there are no pointing input mechanisms) */
@media (any-hover: none) { ... }
 
 
/* At least one input mechanism of the device 
   includes a pointing device of limited accuracy. */
@media (any-pointer: coarse) { ... }
 
/* At least one input mechanism of the device 
   includes an accurate pointing device. */
@media (any-pointer: fine) { ... }
 
/* The device does not include any pointing device. */
@media (any-pointer: none) { ... }

Browser Support Isn’t Bad at All!

Even though this is a working draft, it has pretty good support.

My simple test proved successful on Chrome, Chrome for Android, Safari, Edge, Opera, Samsung browser, and Android Browser, but it didn’t work on [Firefox], Opera Mini or IE.

[…]

I think we are ready to use this feature, and as [Firefox] adds support for it and IE dies once and for all, we will have full support.

Scaling an SVG without scaling the stroke

A few days ago, I ran into a little problem when using SVGs. I’d created a reusable set of SVG symbols for a project I was working on, and started sprucing it up with all the pretty icons my designer gave to me. As we all know, one of the biggest benefits to using SVG is the “scalable” part of it, meaning that graphics render perfectly at and size, no matter the original size of the graphic. I’m a huge fan in general of SVG, and implementing them into this project was a no brainer for me.

However, a few of the icons in the design consisted of strokes, and those strokes were always 1px in width, no matter the size. When you scale an SVG, it scales everything about it, so an icon that’s scaled up two times would have stroke widths that are double the size of the original. One such example was a “+” icon that indicated there was more content. I had to reuse that icon at small and large sizes, but:

  1. I wanted the stroke width at all sizes to be 2px
  2. I wanted to create one graphic that I could reuse at any size without scaling the stroke width

Enter The Vector Effect Attribute

One of my favourite things about programming is being faced with a problem. It challenges you to research and find solutions. In this case, I stumbled upon the vector-effect attribute, which conveniently has an available value called non-scaling-stroke. It does exactly what it says, i.e. prevents strokes from scaling as an SVG scales.

[…]

I’d see a scaled up icon including scaled up effects. This one’s dimensions are 4 times the size of the original view box. As such, the stroke would render at 8px. In order to circumvent this, I added the vector-effect attribute to the paths on the original graphic, and set the value to non-scaling-stroke, like this:

Code language: HTML

<circle vector-effect="non-scaling-stroke"/>
<path vector-effect="non-scaling-stroke"/>
<path vector-effect="non-scaling-stroke"/>
Tags

Style List Markers in CSS

It’s a perfectly reasonable to want to style the marker of list items. You know: blue bullets with black text in an unordered list. Or red counters with knockout white numbers in an ordered list.

There is a working draft spec that defines a ::marker pseudo-element that would give us this control.

Code language: CSS

/* Not supported anywhere; subject to change */
li::marker {
  color: blue;
}

It’s possible to do this styling now, though, thanks to CSS counters. The trick is to remove the list-style, then apply the markers through pseudo-element counters.

Code language: CSS

ol {
  list-style: none;
  counter-reset: my-awesome-counter;
}
li {
  counter-increment: my-awesome-counter;
}
li::before {
  content: counter(my-awesome-counter);
 
  /* Style away! */
 
}

Annotation is now a web standard

Many have tried over the years to bring us web annotations. The lack of standards has been one of the key things holding these efforts back– a need we highlighted in the first of our 12 original principles back in 2013 and have been working towards ever since.

Yesterday, on February 23, things took a giant leap forward when the W3C, the standards body for the Web, standardized annotation.

Twenty four years after Marc Andreessen first built collaborative annotation into Mosaic and tested it on a few “guinea pigs” before turning it off, annotations have finally become first-class citizens of the web.

From the W3C Web Annotation co-chairs, Rob Sanderson and Tim Cole:

“Many websites already allow comments, but current […] systems rely on unique, usually proprietary technologies chosen and provided by publishers. Notes cannot be shared easily across the Web and comments about a Web page can only be saved and viewed via a single website. Readers cannot select their own tools, choose their own service providers or bring their own communities.”

 

So what exactly does this mean for you?

Comment widgets may soon become a thing of the past.

The W3C standards (called Recommendations) are a key milestone towards a future in which all pages could support rich layers of conversation without requiring any action by their publishers—because that capability can be built into the browser itself and be available as a native feature, just like web search. The shared vision is that conversations will be able happen anywhere on the Web, or even on documents in native apps, and inline instead of below-the fold, in a federated, standards-based way.