On CSS’s specificities

Billet en français

Order

  1. By ascen­ding priority:
    1. Ignore pseudo-éléments
    2. tag is the star­ting point
    3. classes and pseudo-classes
    4. id
    5. !impor­tant server
    6. style
    7. !impor­tant client
  2. If a conflict arises bet­ween two ele­ments of the same prio­rity, this is the num­ber of ele­ments of the highest level which win (two id are worth more than one id and fifteen class).
  3. If there is still a conflict (two id versus two id), wri­ting order decides.

Note #1: the CSS2.1 “non-standard” (I don’t like CSS2.1) consi­ders pseudo-elements as classes for prio­rity, contrary to both CSS2 and CSS3 (source).

Note #2: I’m not sure of the order for style et !important. What I wrote is what I deem logi­cal and this is appa­rently also (at least par­tially) the case for Firefox.

Note #3: as said, pseudo-classes order mat­ters too: read Eric Myer on chai­ning pseudo-classes.

The que­sion of the attribute

Beware, an attri­bute refe­ring an id ([id=p123]) is less spe­ci­fic than this id itself (#p123). Conse­quently, these attri­butes are worth less than id. So, I’m still not sure what attri­butes are worth com­pa­red to a class.

Examples

Example #1

div p	{color:green} p	{color:red} <p>coloured text</p>

Green text (two tags vs. one tag; no need for a class or an id to show specificity.

Example #2

p.good	{color:green} p	{color:red} <p class="good">coloured text</p>

Green text (one class vs. no class).

Example #3

#good	{color:green} .good	{color:red} p	{color:yellow} <p id="good">coloured text</p>

Green text (one id vs. no id)

Example #4

#good	{color:green} .good	{color:red} p	{color:yellow} <p id="good">premier text</p> <p class="good">second text</p>

First text in green, second in red (one id ver­sus non id, one classe ver­sus no class)

Example #5

#good	{color:green} .good	{color:red} .damn	{color:red} p.it	{color:red} p	{color:red} <p class="good really damn it">first text</p> <p id="good">second text</p>

First text in red, second in green. An absent­min­ded per­son just mixed up class and id and doesn’t unders­tand why the text is not green (any simi­la­ri­ties with a blog­ger would be purely coin­ci­den­tal)… 3 classes (good, damn, it = 30) and 2 tags (2×p = 4) are not worth one id (100). Notice that by keep adding some, that will finally work (well, I’m not sure)

Example #6

p	{color:red} <p style="color:green">text in couleur</p>

Red text (style vs. no style style). A good way to debug.

Example #7

#good	{color:green} p	{color:yellow  !important} <p id="good">coloured text</p>

Yel­low text (to check). I am not sure that !important ser­ver has prio­rity over style, bit it seems logical.

Example #8

p	{color:green} p	{color:red} <p id="good">text in couleur</p>

Red text.

Equal impor­tance and spe­ci­fi­city: wri­ting order decides.

Example #9

<p style="color:red !important;color:green !important">text in couleur</p>

Green text.

Equal impor­tance and spe­ci­fi­city: wri­ting order decides.

Example #10

p.good	{color:green} p	{color:red} p.good	{color:red} <p class="good">text in couleur</p>

Red text.

We have two classes with the same name and wich define the same pro­perty (color). The second class wins over the first, by vir­tue of wri­ting order. Notice this code is badly-written: the first style shall be dele­ted, since it is over­ri­den by the second one. None­the­less, this is the kind of code one can find on the site of a web­mas­ter who did not rea­lise why it doesn’t work (or with such a long CSS he can’t find out—that hqp­pe­ned to me, I’m not proud of it). Notice that by add­ding p {color:yellow} at the end, the text would stay red, because of the class’ spe­ci­fi­city (but with p.good {color:yellow}, it would turn yellow).

Recom­men­ded readings

Merging title and related text

We all now how bad it is that hN and the fol­lo­wing text are not rela­ted. Well, you may appre­ciate this trick I finalised.

At the heart, it is fairly simple, but the advan­ced part (roun­ded cor­ners) requires Safari night­lies, since indi­vi­dual radii are not yet sup­por­ted by other brow­sers. Notice ano­ther recipe which does not work with Mozilla (too…) had been used here: run-in. Mozilla does not sup­port run-in and this is a known bug since 1998.

Below is a screen­shot of the ren­de­red result. There is also a test­page with all the code, commented.

Merge hN and below

Many thanks to Laura for hel­ping me for the code (by the way, she also as a nice pho­to­blog: Pho­to­gra­phies et belles images).

CSS fundamentals

  • If you need to use !important to make your CSS work as expec­ted, this means your CSS is bro­ken[1]. Believe me there. You must have some kind of inhe­ri­tance or spe­ci­fi­city taking your rule over and using !important will just fix this for a while—maybe no more than the next modi­fi­ca­tion; Rede­sign your CSS.
  • Very pre­cise values consi­de­red harm­ful: When, in order to achieve your layout, you have to rely on a very spe­ci­fic length value (174px), chances are good there is a fun­da­men­tal pro­blem with your CSS, some­thing you shall rethink about. Examples include for­cing cen­te­ring a block because parents are not “logi­cally” cen­te­red but “for­ced cen­te­red” too.

  1. Or, some­times, that your brow­ser is broken.

Shadow scrolling

Have fun with CSS3… again.

Here I am repli­ca­ting a well-known effect that tra­di­tio­nally uses pic­tures. This effect was once dis­played at Surfin’Safari (before it moved to webkit.org) as evi­den­ced by this Archive.org snap­shot.

box-shadow-hack.png
CSS3-generated sha­dow (box-shadow)

I also added some extra effects, just for the sake of it:

  • some border-radius to sof­ten the bor­ders. By the way, notice that border-radius:0 15px 0 15px doesn’t work. I hope it will be fixed, so that it will have the same beha­viours as other properties
  • some border-bottom to fur­ther sof­ten the bor­ders. I chose an inter­me­diate value bet­ween the back­ground and the sha­dow (namely, #dedede). Plus, it helps making it rea­dable on a non box-shadow capable brow­ser (but this is but a nice addi­tion, com­pa­ti­bi­lity had never been in my mind there).
  • a visible title (there is no h1 here!) which is done very easily: head, head title {display:block} (for the detail of the sty­ling, just check the source code below)
  • Almost (background:rgba(255,255,155,.95) opaque back­ground for a nice effect à la CSSE­dit web­site (old layout). Notice how the back­ground is trans­pa­rent enough to show the text but not too much so that it won’t dis­turb you while brow­sing. HSLA would be bet­ter (more intui­tive for the author to set up) but is not sup­por­ted yet. As for opa­city, it doesn’t give exactly the same result (no visible box-shadow with opacity:.95)
  • Some text-shadow, because it is cool:-).
  • A variant on the usual text-stroke (which is not stan­dard: Apple intro­du­ced this effect without W3C’s appro­val, but since CSS3 is still at draft stage, we may expect some changes soon). Here, the texte is white inside (mainly visible on the downs­troke of the s and the o) and black out­side. Thank to the text-fill-color value, the text will appear white inside only to text-stroke–capable brow­sers (pro­vi­ded they really imple­ment it, of course—i.e. not par­tially); For the others, the regu­lar color will be used. This fix the “ren­de­ring hole” in text-shadow (spe­ci­fic longdesc).

At the date of wri­ting, you need Web­Kit (OS X only) to enjoy the whole thing.

And here is the CSS code:

head, head title {display:block} head title { 	background-color:rgba(255,255,255,.95); 	border-bottom:1px solid #dedede; 	color:#222; 	font-family:Didot, serif; 	font-size:200%; 	font-variant:small-caps; 	font-weight:900; 	left:0; 	margin-bottom:2em; 	padding:.6em 0; 	position:fixed; 	right:0; 	text-align:center; 	text-shadow:0 0 5px #111; 	-webkit-box-shadow:0 5px 10px #ccc; 	-moz-border-bottom-left-radius:5px; 	-moz-border-bottom-right-radius:5px; 	-webkit-border-bottom-left-radius:5px; 	-webkit-border-bottom-right-radius:5px; 	-webkit-text-fill-color:white; 	-webkit-text-stroke:2px black } 	body	{margin-top:8em /*compensation for the displayed title*/}

To see a whole page, just click on the first pic­ture.

Below is some lip­sum just to let you enjoy the fading effect pro­vi­ded by the com­bi­na­tion of position:fixed and box-shadow. To bet­ter see it, scroll down slowly.

Lorem ipsum dolor sit amet, consec­te­tuer adi­pis­cing elit. Morbi accum­san, elit et laci­nia porta, quam nisl euis­mod nunc, nec fau­ci­bus metus tel­lus faci­li­sis ante. Sed ac dolor ut quam ultri­cies sol­li­ci­tu­din. Pha­sel­lus feu­giat ali­quam dui. Quisque nec neque. In rutrum, felis non gra­vida posuere, enim enim pha­re­tra nibh, eu lao­reet libero tel­lus eget arcu. Sed nisl neque, cur­sus eget, volut­pat ut, sus­ci­pit sed, leo. Morbi dignis­sim lorem et arcu. Morbi eges­tas. Ves­ti­bu­lum porta euis­mod lacus. Cura­bi­tur tel­lus tor­tor, tin­ci­dunt eget, ali­quet ut, male­suada quis, ligula. Donec feu­giat, elit at rutrum vehi­cula, tur­pis est pul­vi­nar eros, sed dapi­bus lec­tus dui tris­tique massa. Nul­lam a nibh. Sus­pen­disse quis elit a justo rhon­cus sce­le­risque. Ut elit. Ves­ti­bu­lum luc­tus sem ut massa.

Mau­ris nec tel­lus dapi­bus purus ali­quet port­ti­tor. Pel­len­tesque adi­pis­cing volut­pat sapien. Sed sed tor­tor. Mau­ris dolor purus, ele­men­tum luc­tus, ultri­cies viverra, ves­ti­bu­lum at, arcu. Sed arcu urna, sagit­tis vitae, vul­pu­tate eges­tas, condi­men­tum sit amet, ipsum. Sed mi pede, tin­ci­dunt et, volut­pat eu, mat­tis at, nibh. Viva­mus ali­quet. Cura­bi­tur lacus purus, elei­fend id, lao­reet ut, nonummy a, nisi. Nam sed augue. Duis ut diam eget nibh blan­dit pha­re­tra. Viva­mus velit enim, viverra eges­tas, consec­te­tuer a, dapi­bus accum­san, mi. Sus­pen­disse inter­dum faci­li­sis eros. In at eros. Quisque quis augue. Nul­lam vel justo. Sus­pen­disse a mi. Viva­mus lao­reet. Fusce eges­tas quam vel lec­tus rutrum posuere. Morbi sed nisi. Nunc dignis­sim faci­li­sis arcu.

New CSS3 value: text-stroke (WebKit vendor extension)

A new ven­dor spe­ci­fi­ca­tion from Web­Kit: text-stroke. you won’t find it in CSS3 (yet), but this is a long-awaited func­tion (at least by me). As someone said: Web­kit is not only the basis for Safari, though, but an inte­gral part of OS X. Typo­gra­phy has always been a strength of Mac OS1

Sur­ely this the rea­son they imple­men­ted those fancy fonts.

text-fill-color
This pro­perty allows you to spe­cify a fill color for text. If it is not set, then the color pro­perty will be used to do the fill.
text-stroke-color
This pro­perty allows you to spe­cify a stroke color for text. If it is not set, then the color pro­perty will be used to do the stroke.
text-stroke-width
This pro­perty allows you to spe­cify the width of the stroke. It defaults to 0, mea­ning that only a fill is per­for­med. You can spe­cify a length for this value, and in addi­tion the values thin, medium and thick can be used (with ‘thin’ being most like the out­line beha­vior of OS X).
text-stroke
This pro­perty is a shor­thand for the two stroke properties.
<div style="color:#906200;font-size:4em;text-shadow:5px 5px 10px #222;-webkit-text-stroke:5px black">This text has a black 3px stroke and a purple fill.</div>
This text has a black 3px stroke and a purple fill.
text-stroke

  1. If you are not convin­ced (or even if you are), take a look at Du bête RTF and Essayez de faire ça avec le bloc-notes. This is in French, but there is a lot of pictures.

Conflict between border-collapse and border-radius

Bet­ter to know it: border-collapse doesn’t work with border-radius. That makes sense when you think about it, but I had to stumble upon it to rea­lise it.

[ERROR] File extensions are bad: Opera and Firefox discriminate .html and .xhtml

My mis­take: my ser­ver sends eve­ry­thing has text/html—and I don’t have the tech­ni­cal know­ledge to change it.


Conti­nue rea­ding

Have fun with CSS3

I just learnt from the cool guys at CSS3.info that Web­kit now sup­ports box-shadow (text-shadow for blocks). As <a href=« http://webkit.org/blog/?p=86>mentioned on the Surfin’Safari entry, it is great too for new table look, with “floa­ting” cells.

They give some nice pic­tures of drop­ped sha­dows, but back in the day Web­Kit pio­nee­red in sup­por­ting text-shadow, I crea­ted a nice aura effect by using non-dropped sha­dow (and a bit of Uni­code)1. This code abuse page is still there (look for the word radioactivity).

Now, this “text aura” effect may be repli­ca­ted with box-shadow too. The trick for the aura effect is to use a large blur value to illu­mi­nate the block, appa­rently from “behind” (although no z-index had been har­med in the pro­cess. I swear it).

Simple code
<div style="background:#efefef;-webkit-box-shadow:0 0 200px yellow">Radioactivity</div>
Radio­ac­ti­vity

Nice effet, right (pro­vi­ded you are using a bow-shadow–capable brow­ser, of course)? But this is just the beginning.

Now with a bit more code. Fas­ten your seat­belt, Doro­thy. ’Cause pic­tures are going bye-bye.

<div style="background:#000;border:1px solid #000;font-size:300%;border:#461313 medium solid;-moz-border-radius:10px;-webkit-border-radius:10px;font-family:monospace;font-weight: 900;margin:auto;text-align:center;text-shadow:0 0 20px yellow;width:80%">☢ Radioactivity ☢</div>
☢ Radio­ac­ti­vity ☢

☢ Radio­ac­ti­vity ☢

Look Ma’: no picture!

Beware: truly dra­ma­tic effect also require truly dra­ma­tic CPU! (a 20em blur is not for eve­ryone and should not be used in real-life).

Yes, I know that text-shadow (and box-shadow too, I guess) are sup­po­sed to be repla­ced by SVG. Still. This thing rocks.

Oh, stu­pid me. Your brow­ser can’t dis­play it, right? Here’s the pic­ture. Enjoy.

Shadowactivity

  1. Gran­ted, I got my ins­pi­ra­tion from the W3C Eclipse example, but still…
  2. This pic­ture is a 20em blur, very-resource-intensive. If you are using an LCD screen, try loo­king the pic­ture from dif­ferent angles. From below, the blur appear as huge, while in front, you notice it much less.

(X)HTML5: the element is (almost) already there

HTM5/Web Appli­ca­tions 1.0 pro­poses the dialog element.

It will add some­thing on the seman­tic level (the dt is the name of the per­son). But on the pre­sen­ta­tio­nal level (CSS), this is how I’m doing for more than one year:

CSS

dl.run-in, dl.run-in dd			{margin:0}
dl.run-in dt, dl.run-in dt:after	{font-weight:bold}
dl.run-in dt				{display:run-in}
dl.run-in.colon dt:after		{content:": "}

XHTML


<dl class="run-in colon">
	<dt>Person</dt>
	<dd>Speech</dd>
	<dt>Other person</dt>
	<dd>Other speech</dd>
	[…]
</dl>

Pre­view

Luke
A cer­tain point of view?
Obi-Wan
Luke, you’re going to find that many of the truths we cling to depend greatly on our own point of view.

And the adden­dum for a sample style sheet for whatever the name will be:


dialog, dialog dd		{margin:0}
dialog dt, dialog dt:after	{font-weight:bold}
dialog dt			{display:run-in}
dialog dt:after			{content:": "}

For the record: Fire­fox doesn’t sup­port it (I’m reques­ting it out loud), while Opera does for ages; so do Webkit’s nightly builds.

Why choose XHTML 1.0 (strict)

XHTML 1.0 (strict) is bet­ter than HTML 4.01

This recom­men­da­tion allows HTML code to be inser­ted in an XML hub, XML being the new lin­gua franca of the Web

XHTML 1.0 (strict) is bet­ter than XHTML 1.1

XHTML 1.1 doesn’t allow the lang attri­bute any­more, which is repla­ced by xml:lang. This is all well and good, until you want to style foreign words (tra­di­tio­nally by ren­de­ring them as ita­lic). Because xml:lang is not (can not be?) reco­gni­zed by CSS. Of course, one can throw away CSS, but even if dis­car­ding brow­ser sup­port, CSS still wins over XSL:FO (the XML equi­va­lent of CSS).

Choose well, choose XHTML 1.0 (strict).