Forum Moderators: not2easy

Message Too Old, No Replies

Rendering Order of Pseudo Selectors

         

ShamanDev

10:58 pm on Jun 16, 2010 (gmt 0)

10+ Year Member



I'm working on a dynamic cms driven section of a site, and I've ran into a strange and seemingly unsolvable problem.

I'm trying to alternate sides that content, (h4/p tags), and images appear on using floats etc. Works great given that only that type of content layout is used. However, I also need to include the ability for a h4/p to span the full width of the section. No problem using a class on the h4 tag.

Here's where the problem occurs.. I'm using the 'nth-of-type' selector to float odd/even sets of h4/p/img tags left and right accordingly. This works fine until one of these sets follow a h4/p tag that spans with full width without an image. At this point the next img tag will be off by 1 in the DOM tree causing it to be odd when the h4/p tags are now even.

My attempt at a solution, is to use the ':not' selector in conjunction with the 'nth-of-type' so that it will not count h4/p tags associated with the full page width no image content type. Here's the selector I created:

#content-panels-sections div.ui-tabs-panel div.cms-body > h4:not(.full-width):nth-of-type(even), #content-panels-sections div.ui-tabs-panel div.cms-body > h4:not(.full-width):nth-of-type(even) + p:nth-of-type(even)


A long story short, using firebug I noticed that FF was switching the order of the pseudo selectors to 'h4:nth-of-type(odd):not(.full-width)'. If I understand correctly, this mean "select all odd h4 tags, AND THEN not include any that have class '.full-width'.

Is the order switching what is causing the issue, or is it just a bug in how FF (and, safari, chrome, opera) interpret the statement?

Link to page with issue: [danceofthedeer.com ]

alt131

1:57 am on Jun 17, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi ShamanDev and welcome to WebmasterWorld ;)

Note personal links are not allowed - that link will be clipped, but on your description:

I'm using the 'nth-of-type' selector to float odd/even sets of h4/p/img tags left and right accordingly. This works fine until one of these sets follow a h4/p tag that spans with full width without an image. At this point the next img tag will be off by 1 in the DOM tree causing it to be odd when the h4/p tags are now even.
That is what I would have expected - recalling your code seems to be telling the browser to count each h4, p and img independently, so it is not counting the h4/p/img elements as a "set".

using firebug I noticed that FF was switching the order of the pseudo selectors to
There have been some reports of understanding browsers having problems with counting. Most of these relate to dynamically generated content though - so may not be relevant here. But it emphasises the importance of keeping things simple.

Is the order switching what is causing the issue, or is it just a bug in how FF (and, safari, chrome, opera) interpret the statement?
Despite the known issues with counting, and the firebug report. I'd look at all the other things that will be affecting the browser beore concluding this is due to a bug.

Looking at you other post (different issue but included code), and assuming I understand the problem, here are some starting thoughts:
  1. Validate the html and css. Especially the html. This is a basic, but errors make problem-solving really difficult. Unclosed elements etc will cause major problems for the browsers, especially as the selectors are requiring the browser to work its way through all the parent elements.

  2. Simplify the code. The html sample in the other post has lots and lots of divs, all with classes/id's, and the css has been written very specifically. On that small sample, much of those classes/id's (and even divs) seem unnecessary. For example:
    #showcase #slideCanvas .spryEffectSlideItemContainer { ...styles }
    On the code provided, this could have been written :
    .spryEffectSlideItemContainer { ...styles }
    This means that when the browser finds div.spryEffectSlideItemContainer, it does not have trace back up the document tree to make sure it is contained within the two id'ed elements. Simplifying speeds up rendering, as well as providing less opportunity for error (yours or the browser).

    Applied here,
    #content-panels-sections div.ui-tabs-panel div.cms-body > h4 ...
    looks like it could be simplified to
    h4 ...
    or at worse,
    div.cms-body > h4 ...
    If nothing else, it makes it easier for coder and browser to read ;)

  3. That leads to only using a class/id and selecting the elements that need to behave differently: It seems that parent elements have classes/id's, but the h4/p/imgs you are trying to control don't. I wonder if selecting the parent elements is an attempt to "drill down" to the precise unclassed/id'ed h4/p/imgs.

    So reverse the thinking: class/id the element you want to style (or even better, identify the nearest classed/id'ed parent) so you can select the element you are styling directly (as in the eg in 2 above). This avoids classes/id's on all the parent elements, and avoids having to use them in the selector as well. Note this is not about adding more classes - doing this should allow you to remove lots of divs/classes/id's that aren't required.

  4. With that in mind, then tell the browser what you want ;) On the explanation the design has "sets" of h4/p/img's that should be drawn alternatively left and right down the page. Some of these come after h4/p "sets" that are full-width and have an image. Some do not. So it does not seem to matter what comes before the "sets": What is desired to alternatively float "sets" of h4/p/img elements left/right.

    I am loathe to suggest adding more purely presentational elements to the page, but if that is the desired layout, one simple way is to wrap the h4/p/img "set" in a classed div, then use nth-of-type to float the classed div left/right as required.

However, it would be great if you could post some code to see if there is a more elegant solution.

ShamanDev

8:16 pm on Jun 17, 2010 (gmt 0)

10+ Year Member



Thanks alt131 for such a complete response.

I tried your suggestion for simplifying some of the statements. As I thought I run into issues of specificity with the jquery UI tabs styles when I remove everything before 'div.cms-body'.

I should have mentioned, but the large spanning graphic area with spry is out of date and just a place holder so I've removed it from the page. (using all jquery now)

Using a wrapping <div> would be an easy solution, or even requiring a class for <h4> tags that are part of a set that flips sides with a classless <h4> spanning the full width.

The reason I have tried everything I can think of to avoid this, is to allow very simple creation/editing on the cms end. Ideally I'd like someone(in my case and employee with a varying degree of web knowledge) to create/edit a page using a "cheat sheet" so that as long as they follow the proper structure the proper styles would be applied. Requiring alot of class specifications to be made increases the likely hood that the page will break and since the default style is alternating sides, having to apply a class would not be very efficient.

I checked my html structure for missing closing tags but everything appears to be in order.

alt131

12:53 am on Jun 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No troubles with a complete response - a great opportunity to work with the css3 selectors on a live site ;)

... the large spanning graphic area ...
Recall personal links are not allowed, so are not followed.

I tried your suggestion for simplifying some of the statements. As I thought I run into issues of specificity ... when I remove everything before 'div.cms-body'.
Am not sure if you mean you thought simple selectors would create issues, or if specificity issues arose after you tried to simplify.

The code in the other post seems so specific that simplifying one section may result in those simplified rules being overwritten by more specific rules elsewhere. The fix is to remove all instances of unnecessary specificity in the whole style sheet. That may seem like extra work now, but it will reduce the size of the code (making it faster to download) and make it easier and more efficient to read (for both humans and browser).

The reason I have tried everything ... to avoid this, is to allow very simple creation/editing ... Ideally I'd like someone ... to create/edit a page using a "cheat sheet" so that as long as they follow the proper structure the proper styles would be applied. Requiring lots of class specifications ... increases the likely hood that the page will break and since the default style is alternating sides, having to apply a class would not be very efficient.
One purpose of the css3 selectors is to allow the creation of more efficient code. That is, efficient for humans to write, browser and human to read, and browsers to process.

The code on the other post has 9 divs. All of them have an id or class, some have both. That suggests the rest of the code is similar. One more container div will make little difference given the large number of structural elements already on the page, or the number of id's and classes that have to be understood by later editors. Second, if I understand your description, you have been trying to write a rule for each h4, each p and each image. That's three css rules, and they have been getting increasingly complex - increasing the processing time for the browser.

That doesn't seem consistent with code efficiency - so I am still trying to understand the reluctance to avoid one more structural and classed div when that would increase efficiency.

However, I wonder if you think using a container div would require later editors to apply/not apply a class depending on whether the div should float left/right. Not so: exactly what a classed wrapping div will avoid - which is why I suggested it. If the later editor can work their way through the existing code, they should be able to copy/paste each wrapping div and making the necessary alternations with the assistance of a cheat sheet and comments in the html itself.

Also my statement "float the classed div" was misleading. Time to talk in code ;)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title My title</title>

<style type="text/css">
/*Styles for example */
.content {
width:40%;
background-color:#aaa;
margin: 0 auto;
}

.wrap {
width:90%;
background-color:#bbb;
margin: 1em auto;
}

/*basics styles for the h4, p, img sets */
.wrap p {
width:45%;
float: left
}
/* create the alternating float*/
.wrap:nth-of-type(2n+1) p {
color:blue;
float:right;
}

</style>

</head>

<body>
<div class="content">

<div class="wrap">
<h4>One</h4>
<p>My para</p>
<img src="insert image" width="50px" height="50px">
</div>

<h4>My full width title</h4>
<p> my full width para </p>

<div class="wrap">
<h4>Two</h4>
<p>My para</p>
<img src="insert image" width="50px" height="50px">
</div>

<h4>My full width title</h4>
<p> my full width para </p>

<div class="wrap">
<h4>Three</h4>
<p>My para</p>
<img src="insert image" width="50px" height="50px">
</div>

</div><!--end column of content-->

</body>
</html>
Note this assumes the images/paras should alternate left/right down the page. If that is wrong, or this doesn't help, please post some code.

ShamanDev

5:23 pm on Jun 18, 2010 (gmt 0)

10+ Year Member



Thanks for the reply I'll try to respond to each of your responses in order.

I'm a little confused about personal links.. im guessing it has something to do with spam.

I think I didn't clearly explain what I meant about trying simpler selectors. I'm using Jquery UI Tabbed Panels to create multiple content areas. The selectors Jquery uses drill down the DOM tree, so overwriting them means using a higher degree of specificity. When I said I tried simplifying my selectors and ran into issues, I really meant that I was no longer overwriting the jquery ui styles -not that it was changing the behavior of the 'nth-type' selector.

As far as efficiency goes, I think that the reason we're not totally on the same page, is because there are a few constraints that I'm trying to build around that may not be realistic.

Let me first address why I've avoided an additional <div> tag (which would solve the problem). Ideally I'd like to design this section to be editable using a wysiwig editor by someone who writes content but most likely has no idea about html or css but understands formatting headings, paragraphs etc. Requiring they wrap the default layout style in a <div> opens the door for broken pages(misspelled class names, unclosed tags, etc.)

So I guess then, I'm sacrificing easy code reading for developers and browsers for overly simple content editing.

I knew when I started this thread that I was really looking for that miracle, needle in a haystack answer as there are easy fixes that in almost all other cases would work perfect.

Since my current css strategy for this section degrades just fine in IE, I've up until now kept trying and searching for possible solutions.

At this point, if there is no way to correct how the browsers are 'counting', I'll have to resort to wrapping them in a classed <div>.

I may try using Jquery to achieve this effect and see if I get different results.

ShamanDev

6:42 pm on Jun 18, 2010 (gmt 0)

10+ Year Member



*UPDATE*

I wrote some jQuery and it successfully worked. I first tried adding a class, but again ran into my styles being overwritten so I've applied inline styles (very last resort).

heres the code


$(function() {
$("div.cms-body > h4:not(.full-width):odd, div.cms-body > h4:not(.full-width):odd + p").css({'float' : 'left', 'padding-right' : '5px', 'padding-left' : '0'});
$("div.cms-body > h4:not(.full-width):odd + p + img").css({'float' : 'right'});
$("div.cms-body > h4:not(.full-width):even, div.cms-body > h4:not(.full-width):even + p").css({'float' : 'right', 'padding-right' : '5px', 'padding-left' : '0'});
$("div.cms-body > h4:not(.full-width):even + p + img").css({'float' : 'left'});;
});


Pretty sure at this point I'm going to go ahead and use this solution. Curious to know what people think as far as best practices go..

alt131

11:22 am on Jun 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for the explanantion of the constraints.

Opinions vary about using javascript to apply style, but I would never see it as best practise.

At this point, if there is no way to correct how the browsers are 'counting', ...
To me, the thread has still not addressed this original issue.

As stated in my first post, from your description it does not sound as if the problem is necessarily counting. However the only way anyone else can suggest other options for selecting the elements is to post some code.