Web developer tips, tricks, and gotcha's
Beware inline-block nuances
Get rid of any white-space surrounding your
<li>
tags
Inline-block is awesome, and you may be tempted to use it in place of float:left;
on list items. You may then be trying to get the list items to have a very specific gap between them. You will set your margins to zero and still see a gap. This will frustrate you, but it’s correct behaviour. Inline block treats your mark-up differently to plain-old-block, if your <li>
tags have white-space around them, it renders out the white-space - even the one’s outside of the tag itself. To get rid of the gap, you must get rid of any white-space surrounding your <li>
tags.
Try using attribute selectors instead of ID selectors
Try by using
[id='your-id']
instead of#your-id
in your CSS to help avoid specificity issues.
Using ID’s in mark-up is great, it allows for in-page bookmarking for example. But the caveat is that all ID’s must be unique in a page. That means you need to be careful when using ID’s in ‘modules’ or generated contexts (will #comment_2 actually be unique?). That leads to the often smart suggestion of not using ID’s in mark-up. The thing is, sometimes they are appropriate and you should. What you ought to avoid though is using ID selectors in your CSS.
ID selectors have a high specificity, as soon as you use one it can become hard to over-ride that CSS later without also pre-pending the over-ride rule with the selector id. That brings a stronger link between the mark-up nesting than you might like for portability. You can still use the HTML ID as a hook however, whilst avoiding the specificity issue in your CSS by using [id='your-id']
instead of #your-id
. Admittedly it’s rare you’d be well advised to hook onto an id, but it can be useful.
Sibling selectors are not sibling selectors, they’re little-brother selectors
In CSS you will be familiar with the descendent selector. It’s a space and you use it all the time, it means the selector on the right must be descended from the one on the left. e.g., li a
. That targets any anchor that is inside of a list item, no matter how deep inside the list-item the anchor is. You’re also likely to be familiar with the child selector which is more specific, it means that the thing on the right must be directly descended from the thing on the left, e.g., li > a
. That only selects an anchor that is immediately descended from a list-item. So it won’t effect an anchor that is inside a div which is inside a list item (unlike the descendent selector).
Sibling selectors are terribly mis-named because they don’t select siblings, they select a sub-set of siblings: younger siblings. They don’t do what the name says they do.
Are you familiar with sibling selectors? There are two: +
is the adjacent sibling selector, and ~
is the generic sibling selector. As you may imagine, + will only select the elements right next to the prior selector, and ~ will select all of them. So, h2 + p
Will select only a paragraph that is immediately adjacent to a heading. However h2 ~ p
would select all paragraphs that were at the same level as the heading.
Except they don’t. They are terribly mis-named because of a (to my mind idiotic) restriction in how they are applied in browsers (I imagine this is predictability and sensible naming being sacrificed at the alter of “performance” again). They are not sibling selectors at all, they are “little sibling selectors”. They only target elements that are younger (rightmost) to the target. Which makes them useless, and not do what their naming suggests they do. They’re like a bike that can only turn right. Great if you want to go right. Useless if you want to go left.
We still can’t centre vertically if we don’t know an explicit height
For the love of all that is good in the world, I can not see why this is still a problem in CSS. We get hardware-accelerated CSS filters, but we still can’t get a box to centre vertically if we don’t know the box height and container height. Evidently no designers want to do that or no cows have wandered down that path, or all the one’s that did walked off a cliff and were never heard of by the CSS-WG. You might expect vertical-align:middle;
to work. Well, don’t we all. *crickets*
There’s a hack to do it, but the problem with using display:table
is that accessible agents derive a semantic meaning from the CSS declaration and read it out as a table. Yes, I agree that sounds pretty backward to me too, but that’s what happens. Which means the hack is harmful to accessibility. Why the CSS-WG don’t just allow vertical-align:middle;
on non-cell properties I don’t know.
We can’t use % as units for border-width
This one is infuriating given that it makes no sense to arbitrarily limit what a valid length unit is on a given element. A length is a length. Why should % not be valid as a unit on border-width but valid everywhere else?! That’ll be that “performance” thing again I expect. Whatever, it was proposed years ago and shot down. So, for those of us doing nice % based responsive designs, we can’t use a border in them. Not without the math breaking and the layout screwing up entirely. That’s caught me out on every single responsive design I’ve done, and I’ve had to adjust the design each time.
Elsewhere
I’ll just link to an earlier post that remains valid about the utterly basic things CSS still can’t do: CSS needs a bit of basic love
Entry Information
- Posted:
- Wed, 21st Dec 2011 at 12:12 UTC
- Filed under:
- Tags:
-
- no tags defined for this entry
Comments
skip to comment formAn extra tip regarding the inline-block spaces in markup issue:
You can avoid the requirement of removing spaces in markup by setting {font-size:16px} and its #container {font-size:0}.
Obviously ruins font-size inheritance, but used appropriately can be quite useful. Ideally, there should be a CSS rule to do this. I think I've moaned about this before.
Hope it helps someone, and thanks for sharing with everyone, Matt.
Hey that was really needful. Thanks for sharing. I'll surely be looking for more.