Reading List
The most recent articles from a list of feeds I subscribe to.
Component frameworks and web standards
At last year’s Fronteers Conference, I had numerous conversations about the merits of using client-side frameworks for virtual DOMs, declarative templating and routing, versus a classic, vanilla approach to building websites. I had always been a vanilla-fan, but built a recent project in a framework, liked that too, and, well… I think they aren’t the polar opposites that they used to be in my head!
This post has three parts: in the first, I look at what I like about “the web standards stance” or a “vanilla approach”. In the second, I share what I liked when I used a JavaScript component framework. In the last part, I look at whether these two approaches are actually different: maybe I assumed a false dichotomy?
The web standards stance
As I see it, Fronteers Conference has traditionally been very web standards focused. We had no talks about Sass until years after it came about. We did hear about new CSS specs years before they were in browsers. Standards over abstractions. Progressive enhancement and accessibility have been recurring themes from the very first event. I’m not saying any of these things are superior over others, just that learning about them influenced me and many other regulars in our thinking about the web.
Personally, I have until recently managed to avoid JavaScript frameworks in projects. Did I miss out? Maybe. I did my front-end work in teams with a rather traditional stack. Often, they used Node to turn abstractions of HTML, CSS and JavaScript into browser-ready code. But the browser would not be sent much JavaScript and there would be no virtual DOMs.
It’s applying what’s in web standards directly, without a framework that wraps them. I’ll call this the ‘vanilla’ approach. It is basically a very minimal one, with no or few dependencies. Hand-written solutions for just the problems at hand. Some call it ‘not invented here syndrome’, which has a negative connotation, but there are also downsides to whatever the opposite of ‘not invented here’ is (packages can go bad, and what about christmas effects in production?).
I believe going vanilla is a totally valid approach to making sites. Large companies do it. Like GitHub, they even open sourced their components, but also Netflix, Marks and Spencers and others. Going vanilla is controversial, too, I found. When Sara Soueidan tweeted:
It’s really depressing that most useful tools these day are made for React projects and/or require React knowlegde to set up and use. This locks out many of us who are not using React for everything & who still prefer the vanilla route for their projects.
she got various people tell her she should learn React, some very unfriendly. But vanilla is a fine choice too, and more cross compatible, as her point proves: a vanilla component or library could work across multiple ecosystems or outside any ecosystem. A vanilla approach assumes the web itself as its ecosystem or platform.
It’s not just easier cross compatibility though. I have seen in real world projects, including some for very large organisations, that these traditional, vanilla stacks let us have fast, accessible and maintainable sites. By default.
- Fast, because (JavaScript) code you don’t ship to the user, is code they don’t have to download and their browsers don’t have to parse. See also the performance.now() keynote of Steve Souders, “grandfather of web performance”, and Alex Russel’s piece on ‘ambush by JS’: Can you afford it?
- Accessible, because the web is accessible by default. Because web standards are standards, they have the biggest chance of being the thing that makers of assistive technologies adopt to base their tech on. Using a
select
rather than a library that customises one and makes it inaccessible in the process (happens), increases the chance of the component to work for more people - Maintainable, or I should say, maintainable for potentially a longer time, because if you depend on less things, there is less chance your project stops working because of a third factor.
I’m not saying you can’t have these things if you use frameworks. As I said, from real world projects, I learned that traditional, minimal dependency stacks have these benefits. I should note here, you can also get these benefits if you use a framework: giving users more speed and accessibility is also the goal of some frameworks, and there are lots of people in the framework world that are very effective at improving such aspects through framework code.
(Yup, I find accessibility and speed, i.e. aspects that users experience, the most important criteria for judging my tools)
Having said all this, I tried a framework and I loved it! Probably not a surprise, as almost the whole world seems hooked to frameworks.
I tried a framework
In the last few months I built my very first framework-based front-end, in Vue.js. I complemented it with a router, a store and a GraphQL library, in order to have, respectively, multiple (virtual) pages, globally shared data and a smart way to load new data in my templates.
Those of you who work with front-end frameworks will likely nod along to the above description. Others may feel confuses and/or start laughing. Multiple pages, global scope and loading data can be done in web-default stacks with vanilla code. In way fewer lines. Multiple pages by literally creating pages and links between them, global scope by putting stuff in the window object (scoped to your app if you like), loading data with plain old XHR or fetch()
. Why let users download lots of kilobytes of framework code, if the web already has the functionality?
Well, let’s start with things I learned to love. If you have worked with front-end frameworks, you probably want to skip ahead.
Routers
Routers are pretty useful abstractions of which types of pages exists and what data they can have. It took me a lot of uneasy feelings to replace the plain old <a>
’s in my site with instances of Vue Router’s <router-link>
component.
For those unfamiliar with what this means: in an <a>
you use the href
attribute to say where the link goes. A <router-link>
points to a predefined named route
, and accepts in its to
attribute objects for settings that you invent, as well as query parameters.
So if you’d write an <a>
to go to a page with parameters:
<a href="/search?query=css&category=tutorials">
CSS
</a>
you can instead define it as a <router-link>
, a special component that comes with the Vue Router library:
<router-link :to="{
name: 'SearchResult',
query: {
query: 'css',
category: 'tutorials'
}
}"/>CSS</router-link>
(note this is a difference in the template only, the DOM and accessibility trees will only ever see something like the first)
Either is pretty readable. The router link is more abstract, if you don’t construct the URL yourself, you may make less mistakes and it may be easier for others what’s happening. This is not a client-side framework advantage, of course, you can find similar concepts on the server side, like in Flask routing. Routing is as old as the web itself.
The major advantage isn’t readability, it is that the client-side router ties in with the state your website is in. Because it has a fuller picture, it can make useful decisions like to only reload parts of the page. If you link to the same type of page, it may just update the difference in content. This does come with some focus and scroll management challenges, but that’s for another post.
Real components
Ask five people on a web team what a component is, and you may end up with wildly different definitions. Even in our world where most web teams made components central to their way of working, we struggle to mean the same by the word.
As a front-end developer, I’ve long thought of components as a blob of markup, with optional corresponding style and/or script, all living in the same folder. They would have a shared classname on the root element, which would be unique to instances of that component. Just by being in the same folder, they’d be a component for anyone working with the code. They exist because the team agrees not to clash names.
In declarative JS frameworks like Vue and React, components are defined as components. You define each component in the syntax the framework provides. This is arguably more rigid and meaningful than the ‘being in a same folder’ form of defining components I described above. In the case of Vue’s ‘single file components’, the JS knows of a component its name and possible properties (and their types). For associated scripts, it knows the component’s methods, life cycle hooks (a fancy word for: scripts to execute before or after component markup exists in DOM) and event handlers. For styling, it also knows the component’s associated CSS.
Reactivity
All template languages offer some form of variables:
<h1></h1>
The text inside the h1
becomes whatever header
resolves to. When there is reactivity, variables aren’t resolved once, but will update when they need to. For example, if a component is expanded
, the value of expanded
can update from true
to false
, at a programmatically determined time. Following whatever logic your component has for expanding. In online banking, the value for totalBalance
could be reactive and change on some event that is triggered by money coming into the bank account. The credit card logo URL could be reactive and change from mastercard.svg
to visa.svg
based on what credit card number is being typed in. That sort of thing.
Easy to get started
Both Vue and React have a command line tool that creates a project, with lots of stuff built in (create-react-app
and create-vue-app
). This scared me at first, as I was afraid it would by default put stuff into bundles I would send to my users. It turns out a lot of what create-*-app
setups offer is build and testing tools. My least favourite part of making websites is configuring tooling, a ‘just works’ default is good enough for my needs.
Also, wow, there is some very good documentation for these frameworks, that explain just enough to get started, but also let you dive much deeper if you want or need to. It’s all very welcoming and nice.
Thankfully, I also had great colleagues at work and peers at Fronteers Slack that I could direct questions to, have code reviewed by, et cetera. If you want to get started with a framework, I do recommend joining a Slack group for the framework or your area.
What I liked less
Backwards compatibility
Web standards are extremely backwards compatible. Very rarely do HTML tags get deprecated (hi <blink>
!), almost never do DOM methods or ECMAScript features get taken out. This makes sites built with vanilla code future proof. You will likely have to do security updates to old sites, but it is unlikely you’ll have to write your HTML, because someone decided fieldset
s are no longer supported.
If you’re using a framework, the features you rely on are more likely to disappear. When Vue just came out, one would loop through an object like this:
<ul id="tags">
<li v-repeat="tags">
</li>
</ul>
(example from Vue 0.11)
Then v-for
was introduced. My point is, this sometimes happens. Frameworks come up with better paradigms (see also Hooks and Suspense in React). When your site wants to update to a new version, your team needs to rewrite and know what to rewrite. All of Twitter is like “I’ve rewritten this project X to use Hooks”, but this is not trivial, even less so if it is the complicated codebase of your large corporate client.
There are lots of organisations out there using Angular 1 in projects, and I see them struggle to find developers willing to do the work. They’ve since moved on to newer frameworks. The orgs are stuck with outdated paradigms that are incompatible with the now. For freelance front-end developers in The Netherlands, recruitment calls for a certain bank that went all-in on Angular may sound familiar?
I feel this is a real difference between ‘just’ using web standards and buying into a framework. There is also legacy vanilla code, of course. But if that is, as I described in the introduction, very minimal, few dependency code, maintaining it is consequently less involved.
Different origins
I love the origin story of the web, and the idea that it was further developed at an independent consortium and groups like WHATWG. The origins of the big component frameworks are big corporations like Google (Angular) and Facebook (React). Corporations that are more for profit than for humans. Even-though the projects themselves are open source and have volunteer communities full of great humans.
A false dichotomy?
As I described above, there are lots of things to like about using modern JavaScript frameworks to build websites, and a couple of things to moan about. But let’s look now at how that approach differs from ‘just’ using web standards and vanilla code. Let’s look at how it differs from the approach of which I said it gives us good things like accessibility and performance by default. If there is a difference, because maybe frameworks versus web standards is a false dichotomy?
De-facto standards
Various frameworks from the past have inspired web standards. jQuery’s selector engine Sizzle inspired querySelector
/querySelectorAll
. The modern component frameworks seem to diverge towards standard ways of working, both in syntax patterns and in broader concepts, like routing and reactivity. They are not in specs, but they could inspire new web standards. As far as I’m aware, nobody is standardising concepts like reactivity, but there for example this proposal for declarative routing in Service Workers, and among the new proposals in ECMAScript there are many ideas inspired by how people write framework code, like optional chaining. Still, epic standard battles to make features happen are epic.
Framework-browser collaboration
Framework engineers and browser makers collaborate, said React engineer Andrew Clark:
Our team has a regular weekly meeting with Chrome engineers. Sometimes we meet more than once! We’re collaborating on display locking, main thread scheduling, resource prioritization, and more. Great relationship, much credit to @stubbornella and @shubhie
Chrome PM Nicole Sullivan confirmed this:
My favorite part of my job is collaboration with frameworks. The web platform engineers are beyond excited about the tight feedback loops we’ve developed and are developing. We even added getting framework feedback to our intent to implement process.
I don’t really know of such a direct collaboration between framework authors and the Firefox browser. Or other browsers. Such collaborations are quite different from web standards efforts, but I guess they can lead to improved performance and accessibility for large amounts of users. Less “open” improvements, but improvements.
Lots of vanilla code in frameworks components
If I’m comparing vanilla to frameworks, I should also say that within the framework wrapper, I’ve always ended up using vanilla knowledge. Not only is it still important to know which HTML elements there are and what they mean, because framework-based sites yield accessibility trees just like regular sites do. It’s essential to have a deep understanding of all things JavaScript (for instance, everything on Chris Fernandi’s JS roadmap, because the component frameworks offer just that: a framework to get started. Within that, it’s your choice if you want to solve your problems with your own custom solutions, or use libraries, plug-ins, etc Or, of course, and this is common, do either when it makes sense.
Progressive enhancement
Progressive enhancement and client-side frameworks do seem to be hard to marry, because by default they do their work in the browser. There are plenty of ways to make servers do the initial render, but if we are honest this is not trivial. Regardless of where we render, we can and likely should apply a progressive enhancement way of thinking to a framework-based project. To stretch what progressive enhancement means very far: make no assumptions. Not about your user’s devices, not about their permissions, not about their content blockers, not about any other of their choices.
For example:
- if you ultimately want to plot on a map the cars nearest to a user’s location, you could display a list of car locations initially. When users have location abilities, their browser’s support exposing those through the location API and they have granted your site permissions, then try and do the plotting.
- in a project I worked on, we generated identicons on the client. The process involved the Web Crypto API, to convert strings into hashed strings. In browsers that don’t support Web Crypto, we fell back to a hardcoded hashed string. Browsers that got the full thing showed avatars based on people’s username, so they were unique for each user, browsers all showed non-unique avatars based on the string ‘user’.
- you want to lay out a component of your site using CSS Grid Layout. To the 10-20% of browsers that don’t support this spec, you serve a simple fallback, so that all the content is usable, readable and looks not broken.
Conclusion
I love vanilla code, and things that are invented here. Thoughtful developers that solve a problem at hand. I’ve sometimes felt worried that working with front-end frameworks like React or Vue would be at odds with that mental model. I feel I was probably wrong there, there is a lot of grey between vanilla and frameworks, and people do all sorts of cool things on either side to get to solutions that are accessible and performant. This is great. I am glad I tried a framework and found its features were extremely helpful in creating a consistent interface for my users. My hope is though, that I won’t forget about vanilla. It’s perfectly valid to build a website with no or few dependencies.
Originally posted as Component frameworks and web standards on Hidde's blog.
Content-based grid tracks and embracing flexibility
Something I love about CSS is that it lets us define visual design for unknown content. This is kind of magic. We can even size things based on content, with min-content
, max-content
and auto
. This post is about how that works in CSS Grid Layout, and what usage in real projects would mean.
In Grid Layout, there are many ways to size a column or row (I’ll refer to them as ‘track’ from here). You can be absolute and define tracks in pixels, or even centimeters, which is pretty useful if you’re doing print work. You can use relative units too, for example relative to the root element’s font size (rem
), viewport (vw
, vh
, vmin
, vmax
), the width of a 0 (ch
)… any CSS length size, really. Of course, all of these sizing methods can be mixed in grid definitions. For example, you could make one column flexible, the other absolute and yet another one content-based. In fact, that’s often a sensible thing to do.
Why size at all?
In Grid Layout, you don’t have to size anything. If you don’t define (some) track sizes, their size will be auto
, based on the content they need to fit. You could still say which tracks you want with the grid-area
syntax, but leave sizing up to the browser. Or you could refrain from defining areas at all, in which case the browser will create tracks for each of your grid items, then size them.
The obvious reason to define some, most or all of your track sizes anyway, is because you have intentions about your lay-out. You want your content area to have a maximum length for better readability, or you want your ad bar to be certain size for business reasons.
Another reason to give some sizes, is that it saves the browser from parsing your content in order to figure out track sizing by itself, the spec notes:
when content-based sizing is used on an item with large amounts of content, the layout engine must traverse all of this content before finding its minimum size, whereas if the author sets an explicit minimum, this is not necessary
This is not an issue with small amounts of content, the spec concurs that that’s trivial, but it is a potential concern if you have lots of grid items or content.
Content versus context
The go-to CSS spec on sizing is CSS Intrinsic & Extrinsic Sizing Module Level 3. It deals with two ways to size: based on context and based on content.
Context-based or extrinsic sizing of an element is sizing based on the container it is in. This is often its parent, or it could be the viewport. The extrinsic size of a block element is the size of that container, minus padding and border. If you set an element to, say, width: 50%
, it is said to be extrinsically sized to be half of the container.
Content-based or intrinsic sizing, on the other hand, is sizing based on the element’s content, so it is independent from its context.
Before I continue: one place we already have widespread content-based sizing on the web is in tables. They size based on how much content is in the cells. If you place two tables on the same page, they’ll likely differ in size (like the schedule for day 1 and day 2 on the Fronteers website differ). This happens automagically, unless you start setting explicit sizes.
min-content, max-content and auto
So how do min-content
, max-content
and auto
work? Let’s take the following line of text (from Charles Darwin’s On the origin of species, 24):
Some facts in regard to the colouring of pigeons well deserve consideration.
If it is displayed in a browser using CSS, it will sit in a box. The minimum width of that box in order to fit this content, is the size that fully fits the longest word, so without ‘overflowing’. In this sentence that would be ‘consideration‘. To size this box to that word, CSS lets you use the min-content
keyword. If you set width: min-content
onto the element that has this text, it will be sized something like this:
Some facts in
regard to the
colouring of
pigeons well
deserve
consideration.
Note that if your box contains more than just words, more things influence min-content
, for example largest image or fixed size box.
The maximum width of that box is the width of this entire sentence. Think of the width it would require if white-space: nowrap
was applied. To size the box to the maximum that is required for the content, CSS has the max-content
keyword.
Keep in mind that min-content
and max-content
are all about sizing in the inline direction, the one in which words flow, as opposed to the block direction, in which blocks, like paragraphs, flow.
In CSS, we can use the min-content
and max-content
keywords as sizes for elements that contain content. In Grid Layout specifically, we can use the keywords to size tracks. Say you’re using min-content
to size a column, it will be calculated based on the minimum required for content throughout all the rows in that column.
And then there’s auto
. This keyword can mean different things throughout CSS (for a more in-depth look, see fantasai’s Defining auto at CSS Day 2015). For example, in block level elements an auto
width takes up the full available width, while in inline level elements, it takes up just the space needed for the content. In grid tracks, it behaves similar-ish to inline elements, it will take up the space of the content. One exception is that if there is a grid item inside the track that has a size, that size can make the whole track grow.
Embrace the web’s flexibility
As I said above, I really like content-based sizing, so it bugs me that I don’t see it used a lot in real-world projects. Websites don’t need to look the same in all browsers, right? That theory is convincing, at least in the circles of front-end developers and designers, but clients often expect more sameness across browsers than we’d like. Even within teams, this is common.
Going from websites that look the same in all browsers, what about looking the same with all content? Content-based sizing units are potentially very useful, but will they make sense on production websites? I see two potential hurdles: it could still be hard to incorporate them in our design processes, and they could create purposeful inconsistencies that some may see as mistakes.
Design process
One of the hardest problems in designing for the web is that the designer has to deal with unknowns. Websites have CMSes, so content can change. It’s likely unknown. Users come with all sorts of devices and screens, so canvas size is mostly unknown, too.
CSS does a fantastic job at giving us tools to solve that exact problem. If you want a certain amount of characters in a column, you don’t need to know what the characters are in order to get what you want. Just write what the rule is, and the browser worries about how to apply it to actual content. But even if this is solved in CSS, that doesn’t mean it is solved in the tools we design websites in. I have met with designers who write CSS and design in the browser, but design in software like Sketch is also very common.
If we want to use content-based sizing in designs and use design tools that are not the browser, whoever writes the CSS should demonstrate what the web can do. The CSS person can show how flexibly built websites can work better in different languages, on different devices and for different people. Designers and developers can team up, make demos. Browsers can help too, they are improving design tools to expose what’s happening. Tools like the new flexbox inspector in Firefox Dev Tools can bring design and code closer together.
Is intentional inconsistency ok?
What does it mean if subsequent pages end up having slightly (or wildly) different grids? This may create a confusing or “broken” user experience. I think inconsistencies can be very powerful, because they lead to an ideal space distribution. The track that needs most space, gets most space (in an auto
scenario). This is ideal for content, but does it yield the ideal for visual design and user experience? I don’t know, maybe?
Content-based sizing could be most effective in components that exist once on a page, so that there are no inconsistencies. Or in pages that are quite unique, like temporary landing pages and one off sites for conferences, exhibitions and the like.
Wrapping up
With the min-content
, max-content
and auto
keywords, we can size grid tracks based on their content. I think this is very cool. If we manage to embrace as much of the web’s flexibility as we can, we can get the most out of these tools, and let CSS help us with designing for the unknown.
Originally posted as Content-based grid tracks and embracing flexibility on Hidde's blog.
Three ways to build Crouwel's Hiroshima poster in CSS
Recreating old posters, I figured there are at least two approaches to deciding how many grid tracks your component or page needs: one can make it visually perfect, the other is more flexible if content is bound to change.
In the past 1.5 year or so I spread my excitement for flexbox and Grid Layout through workshops. An assignment I used in each one, is to recreate Wim Crouwel’s iconic “Hiroshima” poster using CSS. Poster recreation in CSS is an idea, of course, popularised by Jen Simmons and her awesome Experimental Layout Lab. She has lots of poster experiments on that site, check it out if you have not.
I like having a poster recreation exercise in the workshop, as it lets people learn CSS properties, without worry over maintainability or other concerns that come in mind when doing real-world CSS coding. It also lets the participants build graphic designs that are wildly different from most websites, think outside of the box (oh wait, CSS is ALL boxes, as Hui Jing Chen explains in her Box Alignment talk).
Photos from the exhibition about Crouwel’s work at the Design Museum in London (2010), photos by Ben Terrett. On the right: the original Hiroshima poster.
One poster I like to use is Wim Crouwel’s “Hiroshima” poster. Crouwel is one of The Netherlands’ most influential graphic designers. As co-founder and designer at the influential agency Total Design, he worked on large corporate house styles. He is best known though, for the posters he designed for Dutch museums, including the Stedelijk Museum in Amsterdam. The “Hiroshima” poster was made for an exhibition in the Van Abbe Museum in Eindhoven, The Netherlands. It’s not a complicated poster, sporting the name of the exhibition, a subtitle, location and the opening times.
The letters used for the word “Hiroshima” were manually designed by Crouwel. They have inspired various typefaces, including “Shima” by Nate Navasca, which closely resembles it, and UT Morph by Oscar Cobo.
Column choices
If you look closely, you’ll find that the opening times and exhibition duration align with the stem of the second letter ‘h’. The subtitle aligns with the letter ‘o’. Presumably, this is on purpose.
A column for each stem
One way to design the columns for this poster, is to define a column for each of the stem: 17 in total. The minimal space between the letters can be the grid’s column-gap
. This leaves us closest to what we presume the poster maker intended.
We then need to decide one or more columns to each letter: one for the ‘i’ and three for the ‘m’, for instance.
A column for each letter
Another approach is to create a column for each letter, and let the columns be of auto
width. They will then grow with the letters contained in them.
The content-based choice
We could also base our track choices on the four bits of content (title, subtitle, opening times, exhibition duration). This is a more functional approach, and less precise. The bits of content will likely not fully align with the letters of the word “Hiroshima”.
Ok, show me the code!
I’ve built examples with all three approaches: 4, 9 and 17 columns.
The two extremes: 4 columns and 17 columns, visualised using Firefox’s built-in Grid Inspector.
4 columns
The 4 column has least markup and classnames related to the function of the element in the whole. With just those four columns, it does the bare minimum. Dates and opening times don’t align with the letters they’re supposed to align with. But had someone decided to change the exhibition’s name, little harm would be done.
I approximated the size of the columns by making them all 1 part of the available space:
grid-template-columns: repeat( 4, 1fr );
9 columns
My 9 column version, has each letter wrapped in a span. Only direct children of grid containers get to play in the grid game, but with display: contents
on the <h1>
, it gets skipped and its children become grid items. Warning: do not use display: contents
in production just yet, as the heading will lose its accessible role in most browsers.
In this one, the columns are of auto
size, so that they grow with their content:
grid-template-columns: repeat( 9, auto );
Note that this works because the letters are the largest things in their respective tracks. If we had put anything larger in the same column, for instance in another row, that larger thing would have made the whole column larger.
Because of display: contents
, the span
s within the h1
became grid items. With no explicit placement, they get auto-placed in a column of their own, allowing for alignment of content with the actual letters. With that in place, I then told all span
s to go to the correct row:
h1 span {
grid-row: 3;
}
17 columns
In the 17 column version, I’ve wrapped each letter in a span with a classname. I did not need to space each letter individually, but I did have to address differences in how many columns a letter should span
: the letters ‘i’ require one column, the letter ‘m’ requires three and all the others require 2. I did unique classnames for each letter, with the two h’s and i’s sharing one between them:
.hiroshima-r,
.hiroshima-o,
.hiroshima-s,
.hiroshima-h,
.hiroshima-a {
grid-column: span 2;
grid-row: 3;
}
.hiroshima-m {
grid-column: span 3;
grid-row: 3;
}
.hiroshima-i {
grid-column: span 1;
grid-row: 3;
}
Another, more abstract approach could be to have a span-1
, span-2
and span-3
classname.
What’s better?
Thanks for reading this far in a post that is just about grid columns. Basically, my point is about two approaches: visual perfection versus functional pragmatism. I’ve seen both in real world CSS. Either can be effective. Neither of the two is better, everyone can grid however they like.
I would say visual perfection makes more sense in a promotional type of website, where the site was designed just for one purpose, maybe to communicate a one off event. A conference that you already know the name of. That sort of thing.
The functional approach is ideal when working with a CMS, where content can change, or there are multiple instances of the same design work. It’s more resilient to change.
Originally posted as Three ways to build Crouwel's Hiroshima poster in CSS on Hidde's blog.
Console logging the focused element as it changes
When you build a Single Page Application, chances are that you manage some of the focus
through script. For debugging, it can be super useful to log the currently focused element to the Dev Tools Console.
Logging the focused element
The focused element is known in the DOM as document.activeElement
, so you can just console.log()
that if you want to know what the currently focused element is.
Logging it as it changes
Thanks to Eva, I recently learned a way to log the active element as it changes:
document.addEventListener('focusin', function() {
console.log('focused: ', document.activeElement)
}, true);
The focusin
event is like focus
, but it bubbles, so when any element within document
receives focus, focusin
bubbles all the way up to document
.
When I posted this on Twitter, Christian Schaefer helpfully pointed out that, although focus
does not bubble, it can be intercepted when the capturing
flag (addEventListener
’s third argument) is set to true
. Phil Walton then added that focus
fires also for non-interactive elements and when the window
receives focus. Even better!
So this is what you could use to log the active element when it changes:
document.addEventListener('focus', function() {
console.log('focused: ', document.activeElement)
}, true);
Also relevant: PPK’s Delegating the focus and blur events, over 10 years old, in which he explains that lack of bubbling in focus
makes sense, because we would not want it to bubble to window
, as the `window’ having focus means that the user has focused the entire browser window.
Originally posted as Console logging the focused element as it changes on Hidde's blog.
Linking to translations
The other day I worked on some front-end code that takes users to a version of the website in a different language. Two attributes can make such links more accessible: lang
and hreflang
. What’s the difference?
Strings in another language
The lang
attribute can expose what language a page is in, when it is added to the root tag. For example, a page in English, will likely have this as its root element:
<html lang="en">
You can also use lang
on any tag in a document, to signify a section, paragraph or word is in a different language. This is useful when you link to a translation. If the link text has a different language than the rest of the document, you can expose that.
A link with link text in Chinese, as spoken in Taiwan, one of my favourite countries:
<a href="/zh-TW">
中文
</a>
The same link, now with the language exposed:
<a href="/zh-TW" lang="zh-TW">
中文
</a>
That’s all. Note: this only means that the word within this tag is in a different language. It says nothing about the page we’re linking to.
Words marked up in an HTML element with a lang
attribute, will get read out with a voice in that language in Safari with VoiceOver and some versions of other screenreaders, depending on settings and voice availability
Links to pages in another language
If the page you’re linking to is in a different language, you can use hreflang
to signify that (hreflang in the spec).
For example:
<a href="/zh-TW" hreflang="zh-tw">
Chinese
</a>
If you link to a page in a different language and the text you use is also in a different language, both attributes can be used at the same time.
<a href="/zh-TW" hreflang="zh-tw" lang="zh-TW">
中文
</a>
To be very honest, I don’t know of an actual system using it for detection. Implementing the attribute doesn’t hurt though, if more of us do it, tools can more reliably take advantage of that. The hreflang
attribute is also used by people who want to increase their search engine rankings, in a per page setting exposed via a link
element or as a header.
Language tags: BCP 47
The format of languages used in lang
and hreflang
is specified in something called BCP47.
They consist of one or more subtags, separated by a hyphen (-). The first one is the primary language, for example en
for English and zh
for Chinese (zhōngwén means Chinese writing). Most are two characters, some are more.
There is a list of language tags on the Library of Congress website.
Summary
So, to sum up:
lang
on any HTML element describes what language is used in that elementhreflang
on a link (<a>
) describes the language of the page you’re linking to- both
lang
andhreflang
are in the format described in BCP47
Happy internationalising!
Originally posted as Linking to translations on Hidde's blog.