Rethinking Semantics
The idea came to me when I saw the HTML structure of "instant articles". They have specific rules for the structure of instant articles, and the structure is very clear. I noticed many HTML tags that I hadn't paid attention to before, such as address
, figure
, caption
, and summary
.
Out of curiosity, I looked up the documentation. I found that many semantic tags are already supported by mainstream browsers, and the spec is well-defined. However, most main websites still use the div + class
approach for expressing content. Although some places use header
, I believe there are more suitable semantic tags that can be used. Using semantic tags not only reduces unnecessary class names but also improves the readability and SEO of the HTML. The important thing is that we are writing standard-compliant HTML.
Furthermore, W3C has been promoting semantic tags in HTML5, such as nav
, header
, dd
, dt
, and has removed or discouraged the use of meaningless tags like b
, font
, center
, etc.
The biggest advantage of semantics is accessibility. Most screen readers optimize specific tags. For example, <a>
will be read as "hyperlink", li
will be read as the current list item and its position, <main>
will be read as the main content, and so on. These benefits are brought by using semantic tags.
However, there are countless UI scenarios where semantic tags cannot solve the problem, such as tab switching, dialog, dropdown menus, tooltips, etc. In these cases, you can use the aria-*
and role
attributes to tell the screen reader what the element is doing.
Thoughts on Class Names
After using class names for a long time, I went back to the spec and found the description of class names by W3C.
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 specific usage restrictions on class names, it is encouraged to use class names that describe the nature of the content rather than the desired presentation. This means that expressive class names like col-md-*
are actually discouraged in the W3C spec. However, if we follow this guideline, we might have to start from scratch with all CSS-in-JS approaches. CSS modules hash all class names, and styled-components
also does the same. The advantage of using hashes is to avoid naming conflicts and minimize the size when building for production, which can be significant when there are many elements in the HTML.
Why Conform to Standards?
- Standards are established by committees after extensive research and discussion to achieve uniformity.
- Browsers usually optimize the display of these elements on different devices.
- These standards are usually considered best practices.
- Why should we prioritize saving development time over creating non-compliant web pages?
<!-- Presentation -->
<div class="margin-b-10">
</div>
<!-- Content -->
<div class="user_info">
</div>
This is my understanding.
As for why this situation has occurred, perhaps it is because in the early days of web development, CSS support was not good, and it was difficult to strike a balance between semantics and presentation. That's why purely presentational elements like center
and width
were used. But now, things have changed. We should move towards a semantic era, and this is also what W3C is promoting.
Grid System is Awesome!
I admit that the grid system is indeed a very useful pattern, and there are scenarios where layouts cannot be expressed semantically. However, according to the definition of semantics, we may have to remove the grid system in order to write better-looking and more readable HTML. This would be a major undertaking, but it's better to start early, especially for the current main website structure, whether it's big or small!
- Use Susy.
- @include @extend.
Page Visibility API
It allows us to know if the user is currently focused on the page. In many situations, we want to minimize unnecessary requests or operations when the user is not focused on the web page (e.g., switching to other applications or tabs). For example, Facebook only plays notification sounds when you return to the page. A common scenario is when playing a video. If the user navigates away from the page, we can automatically pause the video and resume playback when the user comes back.
Revisiting JavaScript Event Propagation
I recently went back to the Rhino book to clarify some concepts I didn't fully understand before. There are so many JavaScript libraries on the internet that we may have forgotten the native JavaScript. Although high levels of abstraction are a natural phenomenon in technology development, it is still good to understand the internal workings and have a better concept when writing code!
JavaScript Event Propagation
JavaScript event propagation mainly consists of two types: "bubble" and "capture". Most events use the "bubble" propagation. What is "bubble"? After the event handler of the registered element is called, the event starts to bubble up (excluding certain elements' specific events) and then calls the handler registered on the ancestor element. This phenomenon rises to the document
and finally reaches the window
.
In practical applications, we often see:
$(".abc").on('click', e => {
});
$(".ass").on('click', e => {
});
$(".asass").on('click', e => {
});
These scattered event registrations are difficult to maintain and do not have a unified entry point, making debugging very challenging. Therefore, we can use the bubbling feature of JavaScript events to register events on the document. The second function of jQuery's on
provides event delegation. For example:
$('document').on('click','.sass', e => {
});
This not only reduces scattered event registrations but also provides a unified entry point. If we want to add new events, we only need to extend them on the document. We can even write 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]
}
})
Like this, if we want to add a new event handler, we just need to add it to the actionList
. We can even use the extend
method, so it doesn't have to be written in the actionList
. This greatly improves extensibility.
So why are there so few people using capture? The biggest reason is that lovely IE does not support it. Furthermore, event capturing is only applicable to the addEventListener
method. Event capturing is somewhat the opposite of bubbling. It starts from the ancestor and goes down until the event's parent element's event handling is called, and the event handler registered on the event element will never be called.
Event Cancellation
We often see methods like e.preventDefault()
. In fact, older browsers may not support it, so we can use some tricky methods to cancel events.
function cancelDefault(event) {
var event = event || window.event;
if(event.preventDefault) event.preventDefault()
if(event.returnValue) event.returnValue = false
return false
}