Forum Moderators: not2easy

Message Too Old, No Replies

CSS Specificity.

Sith Power, Stormtroopers ..

         

SuzyUK

4:28 pm on Apr 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Each character (selector) is given its own Sith power (specificity value) depending on how powerful they are in the ways of the Dark Side. A storm trooper is less powerful than Vader who is in turn less powerful than the Emperor.

[Source [stuffandnonsense.co.uk]]

Dabrowski

5:30 pm on Apr 18, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



What about structuring your CSS, Fotiman and Suzy you helped with my sith problem before. If you had 3 nested div wrappers, how would you CSS them so you could style elements within each without getting storm trooper problems?

[edited by: SuzyUK at 5:22 pm (utc) on April 19, 2007]
[edit reason] split from another thread [/edit]

Fotiman

6:10 pm on Apr 18, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




If you had 3 nested div wrappers, how would you CSS them so you could style elements within each without getting storm trooper problems?

Well, each situation is unique. In some cases, it may make sense to give each div layer its own id and target them that way. For example:


<div id="container">
<div id="header">
<div id="intro">

While in other cases it may make sense to apply a class to one or more of the divs, and in some cases it might just make sense to target them as:

div { /* applies to all of them */ }
div div { /* applies to the 2nd and 3rd layer */ }
div div div { /* applies to the 3rd layer */ }

cmarshall

6:30 pm on Apr 18, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This should be required reading for people implementing CSS.

The stuffandnonsense Specificity Wars [stuffandnonsense.co.uk] poster is a true classic.

[edited by: SuzyUK at 5:05 pm (utc) on April 19, 2007]
[edit reason] part of thread split [/edit]

Dabrowski

12:03 pm on Apr 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ok, following your example Fotiman, if you had:

div { /* applies to all of them */ }
div div { /* applies to the 2nd and 3rd layer */ }
div div div { /* applies to the 3rd layer */ }

<div id="container">
<div id="header">
<div id="intro">

I'm sure nobody would ever actually use that? It would be fine if there were no other DIVs on the page, but say inside intro you had another div/h1 combination like discussed earlier in the thread, you then get:

div { /* applies to all of them */ }
div div { /* applies to the 2nd and 3rd layer */ }
div div div { /* applies to the 3rd layer */ }
div div div div { /* getting messy now */ }

<div id="container">
<div id="header">
<div id="intro">
<div class='centered'><h1>Title</h1></div>

And then say you wanted #header absolutely positioned at 0,0 (I know this would probably never happen, but it's hypothetical). You set the position on DIV DIV and that now puts header, intro and centered all on top of each other.

So, I ask again, how would you (or Suzy) do it?

[edited by: SuzyUK at 4:56 pm (utc) on April 19, 2007]
[edit reason] part of thread split [/edit]

Dabrowski

12:06 pm on Apr 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I guess what I'm asking really is how you would use the selectors to avoid sith problems.

Traditionally I have been using things like:

DIV#container { stuff }
DIV#container DIV { stuff }

DIV#header { stuff }
DIV#header DIV { stuff }

DIV#intro { stuff }
DIV#intro DIV.centered { stuff }
DIV#intro .centered H1 { stuff }

And I think a lot of my problems with CSS come from selectors.

Fotiman

2:46 pm on Apr 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




but say inside intro you had another div/h1 combination like discussed earlier in the thread, you then get:

div { /* applies to all of them */ }
div div { /* applies to the 2nd and 3rd layer */ }
div div div { /* applies to the 3rd layer */ }
div div div div { /* getting messy now */ }

<div id="container">
<div id="header">
<div id="intro">
<div class='centered'><h1>Title</h1></div>


Like I said, each situation is different. There are probably very few cases where it would make sense to do it this way vs. defining styles based on the ids.


And then say you wanted #header absolutely positioned at 0,0 (I know this would probably never happen, but it's hypothetical). You set the position on DIV DIV and that now puts header, intro and centered all on top of each other.

If you're getting into absolute positioning, then you definately would want to be targeting elements by their ids. There are other ways to skin that cat, but in my opinion targeting the id makes the most sense in that situation.


I guess what I'm asking really is how you would use the selectors to avoid sith problems.

Traditionally I have been using things like:


DIV#container { stuff }
DIV#container DIV { stuff }

DIV#header { stuff }
DIV#header DIV { stuff }

DIV#intro { stuff }
DIV#intro DIV.centered { stuff }
DIV#intro .centered H1 { stuff }


Well, the leading "DIV" on the elements with an id isn't really necessary. It adds to your specificity (sith power) but since ids are unique, it's not likely that you'd have a rule for more than one type of element with the same id. For example, you generally wouldn't see something like this:

div#intro { /* stuff */ }
span#intro { /* stuff */ }

So I would start by removing those, which would change your stylesheet to look like this:


#container { stuff }
#container div { stuff }

#header { stuff }
#header div { stuff }

#intro { stuff }
#intro div.centered { stuff }
#intro .centered h1 { stuff }

In the examples above, the rules for #container, #header, and #intro all have the same specificity, so the order that they're defined will matter. I might generally increase the specificity for the nested items by doing this:


#container { stuff }
#container div { stuff }

#container #header { stuff }
#container #header div { stuff }

#container #header #intro { stuff }
#container #header #intro div.centered { stuff }
#container #header #intro .centered h1 { stuff }

Now it becomes much more clear. I can see that #intro will be contained by #header, which is contained by #container. It no longer matters what order I define the rules (though I usually try to order them from outter-most elements to inner-most) because we've increased the specificity on those nested values.

*Side note: I generally avoid using uppercase element names in my CSS. For example, I changed DIV to div and H1 to h1 in the examples above. I do that because all of my markup uses lowercase tags. It probably doesn't matter, but I like to keep these as similar as possible.

Dabrowski

10:13 am on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I see. I thought using long selectors was a bad thing, I'd been trying to keep them to a minimum to tidy it up, but then running into problems with my sith.

Thanks for the info, all this has been very helpful to me.

Dabrowski

10:19 am on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



One further thought, can you have 2 elements with the same ID as you can with classes?

Is this approved? How does it effect getElementById?

Robin_reala

12:38 pm on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nope, ids are unique inside a page.

Dabrowski

1:05 pm on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ok then, so in this example where the situation arose, I have...

<div id='wrap'> 
...<div id='section'>
......<div id='content'>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
......</div>
...</div>
</div>

The applicable styles I have are.....

#wrap { stuff } 
#wrap DIV { stuff }
#wrap .repeatedstyle { stuff }
#wrap .repeatedstyle TAG { stuff }

Sorry for using uppercase TAGs, I find it easier to read, until it breaks in something I prefer it. I wonder if XHTML allows it as it requires lowercase HTML <tags>?

I think that's the sortest way of applying the style to repeatedstyle DIVs if I can't replicate the id, does that look about right?

Robin_reala

2:40 pm on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That works, although you could slim it down a bit:

<div id='wrap'>
...<div id='section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

#wrap { stuff }
#wrap DIV { stuff }
#content div { stuff }
#content div TAG { stuff }

Dabrowski

5:52 pm on Apr 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I see, the sith value is lower so it's easier to extend/override later.

#wrap .repeatedstyle { stuff } = 110 sith? 
#content div { stuff } = 101 sith?

I see how that's shortened, it would work in one way as I have no other DIVs inside #content, however it wouldn't work on the whole page, see extension of code......

<div id='wrap'>  
...<div id='section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

<div id='wrap'>
...<div id='other_section'>
......<div id='other_content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

See the inner 2 divs change id's, but wrap is still wrap and the repeated inner div is still there, so this way I only have to define it once instead of 2 or 3 or however many sections there are.

Would:

#wrap DIV DIV DIV

be better? To me that's messy, but it has a lower sith? Would that effect a further nested div? I think not?

Thanks for all this help btw, today I wrote half a site and didn't spend hours fiddling with the CSS, thanks to all this stuff on specificity I can pretty much get things right almost straight away, I hope a lot of people read this one.

Also, the divs in question house lenghtly forms, each #wrap contains 22 input's and for the first time not a table in sight!

SuzyUK

12:28 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



this is where you pull in another stormtrooper (ID) to get MORE Specific..

you would not need for both the inner divs to be named differently just the section one would be enough and would likely make sense as the structure may very well be the same the section though may be different.

e.g.

<div id='wrap'>
...<div id='section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

<div id='wrap'>
...<div id='other_section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

all of the inner divs can be targeted with

#content div { stuff } or #wrap div { stuff }

I would tend to go with the lowest common denominator for general styling which would be

#wrap div {}

then when getting to finer details it would be

#content div {}

this covers both scenarios - then if my "other section" content needed to be different

#content div {everything for all scenarios}
#other_section #content div { only the overriding CSS for this}

pulling in the stromtrooper here is a safety measure it's in the right order in the cascade so I wouldn't really need the extra #content ID in the second selector, but would pull it in here to enforce the fact that I'm deliberately getting more specific for a separate section and to avoid possible conflicts in later sheets! - in this vein, I've sometimes also put blank rules into a sheet to to highlight the fact that selector is an available choice in case later readers/writers find it useful.

If I were categorizing my s/sheet this rule would still likely appear in my stylesheet under the "content" part rather than the "other_section" part

I would however always use the cascade first and foremost, pulling in specificty where necessary or simply as a visual reminder that that's what I'm doing ;)

Suzy

Dabrowski

12:37 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ok, I got it.

I think I've finally got my head around CSS layouts, I converted a site I'm working on from evil TABLEs/IFRAMEs, to friendly DIVs/CSS. Only took me about 2 hours too, it took me 2 weeks to get the TABLEs working in IE with my strict DTD!

Thanks for all the info, you've all been extremely helpful and I've learnt a lot.

cmarshall

3:46 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I do want to make a point here.

If you want people to adopt new ways of doing things, its a good idea to practice good diplomacy.

I'm always barging into new technology communities with little to no prior knowledge of that tech, then learning up on it and rapidly becoming an expert.

During the process, I get sneered at and patronized a lot. I've gotten used to it, so I tend to ignore it and continue to forge ahead anyway.

Think of it as the guy who comes into the party with a mullet, 3/4 sleeve baseball jersey, a six-pack of Rolling Rock beer and Skynyrd CDs.

After a while, he gets a haircut, changes his style and starts listening to the Right Music; but I'm almost never at the forefront of technology. I give it a version or two to straighten out before I go in.

Most people don't do that. A couple of slaps, and they go away, often muttering (blogging) bad things about the community. It takes them a while to go back and pick it up.

I'm learning up on a new tech, and I found members of that community are really gnashing their teeth in anguish over how it's not being adopted in the mainstream. Yet they actually don't want "the mensch" to learn the tech. It seems that they don't want to deal with n00bs and only want to have Patricians practicing their tech.

Too bad.

If it hadn't been for the September that Never Ended, the Internet would still be a footnote.

If they don't make their tech more accessible, and put away their priestly robes, they will be the sole keepers of a dead tech, which would upset me, as I think it is very useful.

CSS is difficult to work with, and applying block-level design is not a simple transition from <table> design. I believe it is a sensible and practical way to go forward, but that rubbishing someone's knowledge base is not a particularly helpful way to get them to "come into enlightenment."

So much of the rhetoric in this transition is berating, patronizing and abrasive that it is actually slowing the adoption of the tech. It is being pushed through by brute force, and I, personally, have been treated quite badly in the past as I was learning it. It has led me to be less-than-friendly towards the originators.

As anyone who has dealt with me knows, I'm actually quite open to helping people to get a realistic idea (not ideal) of new tech. I'm into some pretty heavy-duty stuff that makes people's eyes go googly, but I still have a LOT to learn.

I also get pretty cranky at Kool-Aid. I think that we should encourage each other to think, experiment, explore and extend, just as Dabrowski has done here. He's got some pretty serious chops in many places, and brings a lot to the party.

I'd look at these threads as a lesson.

Fotiman

4:41 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



@Dabrowski and SuzyUK

STOP THE PRESS!

I'm not sure why SusyUK didn't pick up on this, but you can't have 2 elements with the same ID value on a single page. Thus, this example is NOT valid:


<div id='wrap'>
...<div id='section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

<div id='wrap'>
...<div id='other_section'>
......<div id='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

It's not valid because you have 2 divs with the 'wrap' id, and 2 divs with the 'content' id. It seems more likely in these cases that perhaps you really should be using classes. For example, this would be valid:


<div class='wrap'>
...<div id='section'>
......<div class='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

<div class='wrap'>
...<div id='other_section'>
......<div class='content'>
.........<div>Text</div>
.........<div>Text</div>
.........<div>Text</div>
......</div>
...</div>
</div>

SuzyUK

4:54 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm not sure why SusyUK didn't pick up on this, but you can't have 2 elements with the same ID value on a single page.

yes you're quite right Fotiman, one ID per page!

though I have to admit to thinking of it as if it were on different pages (you would normally only have one wrapper div per page?) and thinking that it was more a template for an entire site where you would then only need to change one of the internal nested divs in order to format content differently per page type - blog posts, archive lists, photos etc, TOC etc - been working with CMS templates a bit lately so tend to think in template vision ;)

thanks for picking me up and the clarification!

btw, I'm not saying my way is right or best, just that in the context of the question, I was asked for my opinion, that's how I would go about using the options, while still allowing for page anomalies that may arise.

Sorry if it sounds to you like some of us are preaching cmarshall, really I don't think any of us do that here - just about everything with CSS is a choice - there is so many ways to use it!

As I said to Dabrowski in an earlier thread CSS support wouldn't be what it is today without those who have pushed, and keep pushing, it to its limits, so knock yourself out, and keep pushing :)

Suzy

[edited by: SuzyUK at 4:55 pm (utc) on April 23, 2007]

Dabrowski

5:35 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



During the process, I get sneered at and patronized a lot

Have to admit, I'm guilty of this, but I do always try to explain the solution also.

Think of it as the guy who comes into the party with a mullet, 3/4 sleeve baseball jersey, a six-pack of Rolling Rock beer and Skynyrd CDs

Guilty of this as well. In a metaphorical sense! ;)

I'm into some pretty heavy-duty stuff that makes people's eyes go googly, but I still have a LOT to learn

Don't we all?! But you're right, the only way technology moves forward is by people learning it, then pushing it past the point of what it was designed for, forcing a newer technology so we can all do it again.

just as Dabrowski has done here. He's got some pretty serious chops in many places, and brings a lot to the party

*blush*

It's not valid because you have 2 divs with the 'wrap' id, and 2 divs with the 'content' id

Actually, Suzy mis-quoted me, the second #content was actually #other_content, and s/wrap/sectionwrap/g is probably more truthful.

Ahhhh, I can't believe I didn't spot that. Actually it was a bit of forward planning as I haven't written the second section yet.

So, quoting my original example with that in mind.....


<div class='sectionwrap'>
...<div id='section'>
......<div id='content'>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
......</div>
...</div>
</div>

<div class='sectionwrap'>
...<div id='other_section'>
......<div id='other_content'>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
.........<div class='repeatedstyle'>Text</div>
......</div>
...</div>
</div>

.sectionwrap { stuff }
.sectionwrap DIV { stuff }
.sectionwrap .repeatedstyle { stuff }
.sectionwrap .repeatedstyle TAG { stuff }

Now, I'm right in thinking this will still target the text, because I don't have a

#section DIV
or
#content DIV
, which would otherwise override it.

However I do have:

.sectionwrap LABEL { stuff }
#section LABEL { stuff }
#content LABEL { stuff }
#other_section LABEL { stuff }
#other_content LABEL { stuff }

But that should be ok, as I want each tier to override the last, which it should still do. Ooo I've just noticed something that I guess is fairly obvious but I will bear in mind for the future, the sith in the markup is increasing at each tier, so is it better to use classes on the outside and id's on the inside in general?

Fotiman

7:02 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Here's what I do... If I think I have a group of similarly related items, or items that I might consider having more than one of on a page, then I will use a class. And likewise, if I have something that I think represents a single object, of which I will never have more than one, then I'll use an id. For example:


<div id="featuredArticlesList">
<div class="article">...</div>
<div class="article">...</div>
<div class="article">...</div>
</div>

In that example, I would never have have more than 1 "feature articles list", so I give it an id of "featuredArticlesList". And this unique list can contain multiple "articles", so I give each one a classname of "article".

Now, I might ALSO add a class to the featuredArticlesList container. For example:


<div id="featuredArticlesList" class="articleList">
<div class="article">...</div>
<div class="article">...</div>
<div class="article">...</div>
</div>
<div id="sidebarArticlesList" class="articleList">
<div class="article">...</div>
<div class="article">...</div>
<div class="article">...</div>
</div>

In that case, if there are any styles that apply to both the featuredArticlesList and the sidebarArticlesList, then I might put those in the rules for class "articleList".

SuzyUK

7:08 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That will all work, as has been said earlier, however (if you don't mind me saying) considering this topic came about because of CSS Specificity, and then I read this..

...because I don't have a #section DIV or #content DIV,

I think perhaps you or others might like to read (if you haven't already) about a common condition which can afflict most everyone in their CSS learning curve - I don't mind admitting it did me with my first few CSS sites!

While *you*, or most reading this on a PRO Webmaster board, may know in this case exactly what you're trying to achieve because you're doing both the scripting and designing/cssing the site, not seeing the other side may hamper you from being able to perform a "zen" type makeover which has also been discussed previously - Yes some people do/can do/have done site/template updates by changing the CSS alone - this is not meant to be a smart alex approach, it is meant as a helpful pointer that there may be more to it for some than just "is this possible" or "how would you do it" questions that need answers

Web Development mistakes - "divitis and classitis" in css [google.com]

Divitis and classitis
Adding unnecessary div elements and class attributes.

IMHO, using too many "other section" nested classes and id's defeats the purpose of using specificity as it simply transfers the idea of semantic markup into a forced design tenet? (where you already know your design and try to force it into your markup) - when you do this you have no need for specificity (sith power) as you already have a class/id for every eventuality

If you go back to the zen garden source that we were talking about originally you will see the class names .p1, .p2 used over and over - this is overkill in one way because the likelihood of wanting to individually style each <p> on a text site in real life is highly unlikely, however it's good from the CSS specificity learning curve POV when you see that you can use repeated class names within different ID's and are still able to style them totally differently.

my favourite example of this, which I have used in real life situations, is a simple padding div to overcome box model calculations/layout things and which can be used for second background hook too (until such times as we can add double ones)

<id=header><class=pad>
<id=sidebar><class=pad>
<id=content><class=pad>
<id=footer><class=pad>

the .pad class can be reused and given different values for each individual section/ID

#header .pad {padding: 10px; background: #abc;}
#sidebar .pad {padding: 5px; background: #def;}

or it can simply be ignored until next time you want/need to restyle the template.

if, as your posts are starting to suggest to me, you've got loads of forms, or form elements, I would be thinking about the markup and using semantic fieldsets/legends and then perhaps IDs on the fieldsets..

... loads of ways really ;)

Suzy

Fotiman

7:28 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well put SuzyUK. You'll want to try and avoid throwing in an excessive amount of generic containers, and instead using semantic markup where possible. For example, my last example probably should have been something more like this:


<ul id="featuredArticlesList" class="articleList">
<li class="article">...</li>
<li class="article">...</li>
<li class="article">...</li>
</ul>
<ul id="sidebarArticlesList" class="articleList">
<li class="article">...</li>
<li class="article">...</li>
<li class="article">...</li>
</ul>

[edited by: Fotiman at 7:29 pm (utc) on April 23, 2007]

Dabrowski

8:01 pm on Apr 23, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for all the info, thanks for the link Suzy, I read the "10 CSS Tips to Make Your Lift Easier", it's all very educational.

I think I've got it now, I've got my specificity right, and learned how to spell it.

The reason I have the #section and #content inner DIVs is so I can show/hide them easily when a certain tick box is checked, but the styles on the innermost DIV will always be the same, hence trying to select them from the outer .sectionwrap.

It's all working fine so thanks again for the help, there is one issue though, very strange. I have some P's on the page, completely outside these DIVs earlier on the page. They have 1px border. Only in IE7, you click the tick box and the #section is set to display block/none, the borders on these totally unrelated P's disappears. Any ideas on that one?