Frontend Reflections in a Fast-Changing Landscape
Rethinking Semantics
This thought came to me when I saw the HTML architecture of instant article. They require the architecture of Instant Articles to strictly follow their specifications, and the resulting structure is remarkably clear. Inside, I noticed many HTML tags I had never paid much attention to before, such as address, figure, caption, and summary.
Out of curiosity, I looked up the documentation and related specs. It turns out that many semantic tags are already supported by all major modern browsers, and the specs are clearly written. Yet, most main websites still rely heavily on the div + class approach. Even if some places apply <header>, there are still many more appropriate semantic tags that could be used. Beyond eliminating unnecessary class names, using semantic tags improves HTML readability and SEO. Most importantly, we are writing standard-compliant HTML.
Moreover, the W3C has actively promoted semantic tags in HTML5—such as nav, header, dd, dt, and so on—while deprecating or removing meaningless tags like b, font, and center.
The greatest benefit of semantics lies in accessibility. Most screen readers are optimized for specific tags. For example, when encountering an <a> tag, a screen reader announces it as a hyperlink; for <li>, it reads out the current list and which item you are on; for <main>, it announces the main content area. These are all benefits brought by semantic tags.
However, UI use cases are endless, and it is impossible to handle every scenario with existing HTML tags alone. Things like tab switchers, dialogs, dropdown menus, and tooltips cannot be solved purely with semantic tags. In these cases, you can turn to the aria-* attributes and role to inform screen readers what an element actually does.
Thoughts on Classes
After using classes for so long, I went back to check the spec and found how the W3C describes classes:
There are no additional restrictions on the tokens authors can use in the class attribute, but authors are encouraged to use values that describe the nature of the content, rather than values that describe the desired presentation of the content. -w3c
Although there are no strict rules governing how classes must be used, authors are encouraged to use classes to describe an element’s content rather than its presentation. In other words, presentational class names like col-md-* are actually discouraged by the W3C spec. If we strictly follow that reasoning, though, almost all CSS-in-JS approaches would need to be torn down and rebuilt from scratch. CSS Modules hashes all classes, and so does styled-components. The benefit of hashing is avoiding naming collisions while enabling aggressive minification during production builds. When an HTML document contains many elements, the size savings are substantial.
Why Follow Standards?
- Standards are formulated through research and extensive discussions by committees, designed for everyone to follow in order to achieve consistency.
- Browsers have usually already optimized how these components render across different devices.
- These specifications typically represent best practices.
- Why put the cart before the horse by writing non-standard web pages just to save development time?
<!-- 元素展現 -->
<div class="margin-b-10">
</div>
<!-- 內容 -->
<div class="user_info">
</div>
That is my understanding of it.
As for why things ended up this way, it might be because CSS support was poor in the early days of the web. It was difficult to strike a balance between semantics and presentation, which led to the creation of purely presentational attributes/tags like center and width. But we are no longer in that era of constraints. We should move toward an era of semantics—which is precisely what the W3C has been advocating.
Grid Systems Are Awesome!
I admit that grid systems are indeed a very useful pattern. In real-world scenarios, we often encounter layouts that cannot easily be expressed semantically. However, according to the definition of semantics, in order to write cleaner and more readable HTML, we may eventually have to remove grid systems. That will be a massive undertaking, but for a site architecture that is neither too large nor too small, the earlier we start, the better!
- Using Susy
- @include @extend
Page Visibility API
This API lets you know whether the user is currently focused on the page. In many scenarios, when the user is not actively viewing the web page (perhaps they switched to another application or tab), we want to minimize unnecessary requests or operations. Facebook also seems to play notification sounds only when you return to the page. A common use case is video playback: if the user navigates away from the page, we can automatically pause the video, and once the user returns, resume playback.
Revisiting JavaScript Event Propagation
Recently, I picked up the Rhino Book (JavaScript: The Definitive Guide) again, mainly to clarify concepts that I hadn’t fully understood before. With so many JS libraries flooding the web, have we forgotten native JS? While high-level abstraction is a natural consequence of technological progress, understanding how things work under the hood is always valuable—it gives you a much clearer mental model when writing code later on!
JS Event Propagation
JavaScript event propagation is primarily divided into two phases: bubble and capture. Most propagation uses bubble. What is bubbling? After the event handler registered on the target element is invoked, the event starts floating upward (excluding certain specific events on certain elements), triggering handlers registered on ancestor elements. This propagation continues all the way up to document, and finally reaches window.
In practice, we often see code like this:
$(".abc").on('click', e => {
});
$(".ass").on('click', e => {
});
$(".asass").on('click', e => {
});
Scattering event registrations all over the place not only makes maintenance difficult, but it also leaves no single entry point when searching through the code, making debugging very painful. Instead, we can take advantage of JS event bubbling to register events centrally on document. jQuery’s .on() provides event delegation via its second parameter, like so:
$('document').on('click','.sass', e => {
});
This not only cuts down on scattered event listeners, but it also centralizes the entry point. When you need to add an event, you only need to extend it at the document level. We can even write our HTML like this:
<a class="js_action" data-action="foo">
<a class="js_action" data-action="bar">
var actionList = {
foo: function(),
bar: function()
}
$('document').on('click','.js_action', e => {
if(typeof e.target.dataset.action === 'function'){
actionList[e.target.dataset.action]
}
})
With this pattern, adding a new event handler in the future simply means adding a function to actionList. Combined with an extend approach, handlers don’t even need to be defined directly inside actionList. This significantly improves extensibility.
So why do so few people use capturing? The biggest reason was that beloved old IE didn’t support it. Furthermore, event capturing can only be used with addEventListener.
Event capturing is essentially the reverse: it starts from the top ancestor and travels downward until the event reaches the target element’s parent where the handler is triggered; event handlers registered on the target element itself during the capture phase are not invoked in the same way.
Canceling Events
We often see methods like e.preventDefault(). Older browsers did not support this, so we had to use slightly trickier workarounds to cancel events:
function cancelDefault(event) {
var event = event || window.event;
if(event.preventDefault) event.preventDefault()
if(event.returnValue) event.returnValue = false
return false
}
Related Posts
- Recreating My Room with Three.js Using React Three Fiber, I brought my real room into the browser—turning physical objects into an interactive table of contents, and using spatial memory to tell the story of my life and work over the past few years.
- Things to Keep in Mind When Using Images in Frontend Development Expanding on Jake Archibald's article, this post organizes how modern responsive images should be written: why width/height are still necessary, when to use CSS aspect-ratio, how to choose between AVIF and WebP, and using picture/source/srcset for art direction on mobile devices.
- CSS field-sizing — Auto-resize Form Elements with a Single Line of CSS Previously, auto-resizing a textarea required listening to scrollHeight in JavaScript. With CSS field-sizing: content, a single line replaces it all, supporting textarea, input, and select. This article covers the pain points of older approaches and how to use field-sizing.
- Make Your Link Underlines Look Better: text-underline-offset By default, underlines sit very close to the text. Some designers dislike this look, and personally, I don't think it looks great either.