The placeholder
attribute instead of the label
element
Please, stop using the placeholder
attribute instead of the label
element. People that use screen readers can't fill in input fields because screen readers can't read the text from the placeholder attribute.
<input type="email" placeholder="Enter your email">
I recommend using the label
element for a field name and the placeholder
attribute for an example of data that users should fill in.
<label for="email">Enter your email</span>
<input id="email" type="email" placeholder="e.g. example@gmail.com">
The img
element for decorative graphics
I often see developers confuse decorative graphics with content pictures. For example, they mark up social icons using the img
element.
<a href="https://twitter.com" class="social">
<img class="social__icon" src="twitter.svg" alt>
<span class="social__name">Twitter</span>
</a>
But social icons are decorative icons that help users faster to understand the meaning of elements without reading text. If we remove icons we won't lose the meaning of elements. So the background-image
property is the best way.
<a href="https://twitter.com" class="social">
<span class="social__name">Twitter</span>
</a>
.social::before {
background-image: url("twitter.svg");
}
resize: none
When you disable resizing textarea using resize: none
you worsen accessibility. So the user can't comfortably enter data for himself.
textarea {
width: 100%;
height: 200px;
resize: none;
}
You can use the min-width
, max-width
, min-height
and max-height
properties that to limit elements' sizes. Users can fill in input fields a comfortable way for himself.
textarea {
min-width: 100%;
max-width: 100%;
min-height: 200px;
max-height: 400px;
}
Using display: block
with position: absolute
or position: fixed
I often see the following code snippet:
.button::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
}
Here display: block
isn't necessary because if position: absolute
or position: fixed
is used browsers set display: block
by default. So the following code is a full alternative to the previous one.
.button::before {
content: "";
position: absolute;
top: 0;
left: 0;
}
outline: none
I can't use websites using my keyboard. I can't go to a link. I can't register. That happens because developers disable focus on elements when they add outline: none
.
.button:focus {
outline: none;
}
/* or */
.button:focus {
outline: 0;
}
If you need to disable default focus don't forget to make the alternate focus state.
.button:focus {
outline: none;
box-shadow: 0 0 3px 0 blue;
}
Empty elements
There is the practice of using empty HTML elements to style elements. For example, the hamburger markup using the empty div
or span
elements:
<button class="hamburger">
<span></span>
<span></span>
<span></span>
</button>
.hamburger {
width: 60px;
height: 45px;
position: relative;
}
.hamburger span {
width: 100%;
height: 9px;
background-color: #d3531a;
border-radius: 9px;
position: absolute;
left: 0;
}
.hamburger span:nth-child(1) {
top: 0;
}
.hamburger span:nth-child(2) {
top: 18px;
}
.hamburger span:nth-child(3) {
top: 36px;
}
But you can use the ::before
and ::after
pseudo-elements and achieve similar results.
<button class="hamburger">
<span class="hamburger__text">
<span class="visually-hidden">Open menu</span>
</span>
</button>
.hamburger {
width: 60px;
height: 45px;
position: relative;
}
.hamburger::before,
.hamburger::after,
.hamburger__text::before {
content: "";
width: 100%;
height: 9px;
background-color: #d3531a;
border-radius: 9px;
position: absolute;
left: 0;
}
.hamburger::before {
top: 0;
}
.hamburger::after {
top: 18px;
}
.hamburger__text::before {
top: 36px;
}
.visually-hidden {
position: absolute !important;
clip: rect(1px, 1px, 1px, 1px);
width: 1px !important;
height: 1px !important;
overflow: hidden;
}
P.S
โ๏ธ I make unlimited Q&A sessions about HTML/CSS via email with expect responses in 2 days.
๐ I make HTML/CSS reviews of your non-commercial projects and recommendations for improvement.
๐งโ๐ซI help in searching high-quality content about HTML/CSS
Please, use my email for communication ๐ melnik909@ya.ru
๐ช Discover more free things from me
Top comments (18)
Nice, some good points. This is really short-sighted though: "Using display: block and position: absolute (fixed) together". In all browsers? In one browser? What if a user agent is configured differently? Chrome makes changes to their user agent stylesheet all the time. I would never discourage someone to leave out something as important as a display property if they want to explicitly define it. Sure, there are some we've all gotten used to over the years, but by no means would I consider this a "mistake". What if said element is a table and said user wants to absolutely position it as a block element? Be careful with how you are categorizing these as "mistakes".
I have not thought about this before. So I checked it with a CodePen and found this sentence in the Specification:
I assume that these words about "new containing block" force browser developers to display absolutely positioned pseudo-element as a
block
.No they don't.
display:inline-block
,display:table-cell
anddisplay:list-item
all establish containing blocks, so any of those would also be consistent with that sentence from the spec. What you are looking for is section 9.7 Relationships between 'display', 'position', and 'float', step 2In Chrome. IE, Edge, Firefox, Safari, Android, Safari on iOS, UC Browser, Samsung
Any mistakes authors when writing headlines?
Only can judge him.
(It's all love;))
Although I agree with most of the points, I find the headline a bit misleading - are these the "most common mistakes"? I must confess, I've never seen the "resize:none" - setting somewhere in the wild for textareas but honestly, I've also not payed attention to that :).
I definitely agree with the misusage of the placeholder - that also goes for UI designers, who misuse the placeholder already.
Relating to the usage of label, I'd recommend to extend the example with an id for the input-field and a relating for-attribute for the label-tag.
<label for="email_field">
Email:<input type="email" id="email_field" />
</label>
That makes it more relateable where the label tag relates to :).
Wouldn't it be nicer to wrap icons in figure elements and with a figcaption to help users with screenreaders?
This depends on a case
can you elaborate ?
Cool! :)
Did you count how many famous boilerplate templates have the "bad practice" hamburger menu? ๐คฃ๐คฃ
Awesome Article!
I've lost count
That moment when i realized i did all of that mistakes...
Don't worry. Now you know more and can fix it!
Nice one, good job mr Stas.
Thank you!
Nice article! Helpful :)