The Less-Common CSS Selectors

Published:
When applying CSS to your HTML, there are many different ways to select which element(s) the CSS applies to.  Some of these selectors are more commonly known and used than others - Here are the more common ones:
#X - Matches an ID of X
.X - Matches a class of X
X Y - Matches an element Y that is a descendant of X.  (children, grand-children, etc)
X > Y - Matches an element Y that is a direct child of X
Those cover most of the cases where you need to apply styles to your elements, but there are often rules you need to create which need more finely-tuned selection.  

Some of the less frequently used (but still handy) selectors are:
X + Y - Matches any element Y directly AFTER (not inside) an X
X ~ Y - Matches any element Y which is after an X, where both share a common parent.  (think of it as a younger brother rule)
[attribute=value] - Any element with an attribute = "value"
[attribute*=value] - Any element with an attribute containing "value"
[attribute^=value] - Any element with an attribute beginning with "value"
[attribute$=value] - Any element with an attribute ending with "value"

Selector X+Y (adjacent siblings)

Let's say you set the top and bottom margins of every <P> to be 20px each.  That's probably fine in most cases within your site, but what if you have the following?
<style>
                           h2 {margin-top: 20px; margin-bottom: 20px;}
                      </style>
                      
                      <h2>This header has 20px above and below</h2>
                      <h2>This header has 20px above and below</h2>

Open in new window

Because the bottom of header 1 has 20px and the top of header 2 has 20px, you'll see 40px between the 2 headers.  Probably not what you wanted... To solve this, you need a rule that says "Put 20px on top and bottom of each H2, unless that H2 is below another H2.  In that case, remove the top 20px and leave 20px below it."  It sounds impossible, right?  Style sheets can't be aware of what other content is on the page!  I recently had that discussion with a visual designer on a project I was doing, and insisted the CSS couldn't support that request.  A week later, I found adjacent siblings in CSS and agreed that it could indeed be done as he asked.

The format for that is "X + Y" which says that any Y immediately after (not inside) an X gets this style.  So that would work for the example above by saying:
<style>
                           h2 {margin-top: 20px; margin-bottom: 20px;}
                           h2 + h2 {margin-top: 0 margin-bottom: 20px;
                      </style>
                      
                      <h2>This header has 20px above and below</h2>
                      <h2>This header has 20px below</h2>

Open in new window

It's true that in a case as simple as this you might be able to get away with simply having space ABOVE all of your H2 tags if everything else is styled appropriately... but the real world is very rarely as neat and tidy as this.  The adjacent sibling selector is most often used  when you encounter an exception to the normal rules.  Its much easier to add a "what if" rule than have to redesign all of your other elements to handle that one odd case in your content.

Selector X ~ Y (general siblings)

I like to think of this as the younger brother rule... it will select any Y that shares a parent with X, and comes after X.  This one is only available in browsers that support CSS3, so it will not work in older browsers.  Because of its very specific rule, there may be limited uses for this selector - but it's a good one to keep up your sleeve and pull out when you need it!

In the example below, consider the possibility that you need to target any SPAN inside a .parentDiv that comes after an IMG.  By using .img ~ span you'll select the span "Style this one" but not the first one.
<div class="parentDiv">
                           <span> Don't want to style this one</span>
                           <img class="olderBrother">
                           <img class="middleBrother">
                           <div>Element with no class or ID</div>
                           <span>Style this one</span>
                      </div>

Open in new window

Attributes

Most of the other selectors will target an element or set of elements (A, DIV, IMG and so on) but with the attribute selectors you can target a subset of those elements based on their attributes.  A perfect example of this is styling links based on their target window, protocol or file extension.

Many sites have a small symbol next to any link that will open in a new window.  Of course when you're coding these links you could add a class to the <A> tag and have that class display a background, padding and such.  That would work, but requires extra coding and needs to be done manually on every link.  (It also rules out any dynamically created links, unless the code that generates it also adds the class.)  To simplify your code and make it work no matter how the link is generated, add a CSS attribute selector.
a[target='_blank'] {
                      	padding-right: .9em;
                      	background-image: url(images/extlink.png);
                      	background-repeat: no-repeat;
                      	background-position: right center;
                      	background-size: 0.75em;
                      }
                      
                      a[target='_blank']:hover {
                      	background-image: url(images/extlink_light.png);
                      }

Open in new window

The above CSS will apply to any A tag where the target is equal to "_blank" (meaning a new window will open.)  Notice that you can also create a selector for when you hover over an A with a target of "_blank" by adding the :hover just like you would a normal A:hover selector.

If your links won't necessarily have a target attribute set, and you want to set a style for any link beginning with "http://" (which in most cases would mean that the link is going to a different web site) you can change the = to be ^=.  This checks for a value BEGINNING with what you specify, rather than looking for an exact and complete match.  The example below will turn all links to secure (HTTPS) sites red.
a[href^='https://'] {
                      	color: #f00;
                      }

Open in new window

Another common feature you can apply to your links is appending an icon to let the user know if they'll be downloading a .PDF file, a .DOC file, etc.  Also easy!  By replacing the = with $= you tell CSS to apply styles to any link ENDING in the value specified.  In this case, if the filename ends in ".pdf", add some space and a PDF icon.
a[href$='.pdf'] {
                      	padding-right: .9em;
                      	background-image: url(images/pdf-icon.png);
                      	background-repeat: no-repeat;
                      	background-position: right center;
                      	background-size: 0.75em;
                      }

Open in new window

The examples given above might lead you to think the attribute selector only works on A tags... this is not the case.  Any tag with attributes can be selected in this manner... for instance an IMG with the ALT text of "Login" would be

img[alt='Login']

Open in new window

Or if you wanted to style any IMG with the word "important" anywhere within the ALT text, you can use another variation of the attribute selector.  Replace the = with *= and it will match if the value is contained at least once in the attribute.  (Meaning that if your ALT text is "important and super important" it will still be matched by img[alt*='important'].

References:

4
2,345 Views

Comments (2)

CERTIFIED EXPERT
Most Valuable Expert 2013

Commented:
No problem leaving it around, so long as you plan to keep working on it :)

And I fixed the other comment for you.

Author

Commented:
Coincidentally, the morning after this article was published I was looking for a way to clean up the content of some RSS feeds coming into my personal website.  The content contains a lot of blank spaces, caused by back-to-back <br> tags.  

Since I'm using jQuery on my site, the removal part was easy with the .remove() function, so all I needed to do is figure out the best way to select multiple BR tags.  I tried the adjacent sibling selector from my recent article, and it worked perfectly!

$('br + br').remove();

Open in new window

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.