📜 ⬆️ ⬇️

Semantics for CSS selectors and combinators

The syntax of CSS is simple, and to understand it you don’t need to have a doctorate degree in IT. However, this is one of the few popular languages ​​that is not logical in the most direct sense of the word. Unlike other web programming languages, such as JavaScript and PHP, CSS does not solve problems using simple logic. Algorithms like “if X, then do Y, otherwise do Z” or “select all Y, then do X with them” cannot be implemented in a language like CSS. Simply put, it is a language created for decoration, a language for designers, not developers. Some of the experienced programmers I worked with, for this very reason, spent a lot of effort on mastering CSS.

CSS learning begins with classes and IDs, as well as with use. and # to directly identify elements. This is enough to build a full-featured website, but this is not a flexible enough solution in case of a complete change of design. Let's take a look at an alternative approach to managing such hard-to-reach items.

Neighbor Related Combiner

Let's start with the selector, which is convenient in difficult situations - from the neighboring relative combinator. An adjacent sister combinator is indicated by the combination of two elements using the + sign:

  h1 + p 

This highlights the next p-element immediately after the h1-element in the DOM. Typographic theory suggests that we should use indents in paragraphs of text, but only if they follow another paragraph. In practice, this can be used to indent all paragraphs except the first:
 p + p { text-indent: 1em; } 

It is much more convenient than selecting the first paragraph with class = "first". Three lines, no classes and full browser support. If you place img tags related to site content inside the p tags (as you should do), you can simply move their left fields back using the negative value -1em:
 p + p img { margin-left: -1em; } 

Pretty simple, right? But what if we want to highlight the first line of all paragraphs that appear immediately after the headings, without changing all the other paragraphs? Again we can use the view class. A simple selector made from a neighboring compound combinator and a pseudo-element will do the task:
 h1 + p::first-line { font-variant: small-caps; } 

Note: The pseudo-element: first-line is adopted in CSS 2.1, CSS 3 uses the entry :: to establish a distinction between pseudo-classes and pseudo-elements.
')
Hereditary Combinator

A typical markup protocol is the placement of sections in a named element in #page or #wrap:
 <div id="page"> <header></header> <article> <section id="main"></section> <aside></aside> </article> <footer></footer> </div> 

Regardless of whether you are using HTML 5 or XHTML 1.1 syntax, this basic format should look familiar to you. If your document has a fixed width of 960px, is centered, and each element is horizontal, your CSS most likely resembles:
 #page { width: 960px; margin: 0 auto; } header, article, footer { width: 100%; } 

Perhaps you are more accurate in your work, and to avoid unwanted changes in top-level elements, you use:
 #page header, #page article, #page footer { width: 100%; } 

There is a better way. We are all familiar with the universal selector *. If you combine its use with a hereditary selector, you can select all the elements that are direct descendants of #page, without any influence on the "grandchildren" elements:
 #page > * { width: 100%; } 

In the future, this will help you add or remove top-level elements in the document. Returning to our initial markup scheme, this will affect the header, article, and footer elements, but will not touch #main and everything else inside the article element.

String and Substring Attribute Selectors

Attribute selectors are one of the most effective. They also existed in CSS 2.1 and were commonly used in the form input [type = "text"] or [href = "# top"]. But CSS3 offers a deeper level of control in the form of strings and substrings.

Note: so far everything that we have discussed is related to the CSS 2.1 standard, but now we are entering the territory of CSS3.

There are four basic string attribute selectors, where 'v' = value, 'a' = attribute.
v is one of a list of values ​​separated by a space: element [a ~ = "v"]
a begins with v: element [a ^ = "v"]
a ends with v: element [a $ = "v"]
a contains the value: element [a * = "v"]

The potential of string attribute selectors is virtually infinite, but icons are a great example. Let's say you have an unordered list of links to profiles in social networks:
 <ul id="social"> <li><a href="http://facebook.com/designfestival">Like on Facebook</a></li> <li><a href="http://twitter.com/designfestival">Follow on Twitter</a></li> <li><a href="http://feeds.feedburner.com/designfestival">RSS</a></li> </ul> 

Putting them in order is as easy as making a query through their href attribute to find a keyword. We can arrange them in this way:
 #social li a::before { content: ''; background: left 50% no-repeat; width: 16px; height: 16px; } #social li a[href*="facebook"]::before { background-image: url(images/icon-facebook.png); } #social li a[href*="twitter"]::before { background-image: url(images/icon-twitter.png); } #social li a[href*="feedburner"]::before { background-image: url(images/icon-feedburner.png); } 

Similarly, you can select all links in PDF documents with the Suffix attribute selector:
 a[href$=".pdf"]::before { background-image: url(images/icon-pdf.png); } 

Browsers that do not support attributes of substrings in CSS3 will not show these icons, but this is not so important - they are just a nice addition, without any special functionality.

Structural pseudo-classes

Finally, I would like to outline the benefits of using pseudo-classes (not to be confused with pseudo-elements and pseudo-classes link and state). We can use them to select elements based on their position in the DOM. A good example of the use of a structural pseudo-class is the selection of the first (or last) element in the element tree, or the choice between even and odd elements.
 <ul> <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> <li>List Item 5</li> <li>List Item 6</li> </ul> ul li { border-top: 1px solid #DDD; } ul li:last-child { border-bottom: 1px solid #DDD; } ul li:nth-child(even) { background: #EEE; } 

Note: the only pseudo-element available in CSS 2.1 is: - first-child. All other pseudo-elements, including: last-child, belong to the CSS3 standard.

However, you need to know when to NOT use structural pseudo-elements. They should be used solely to highlight an item by its position, and not by its content. If you want to perform any action on an element regardless of its location in the DOM, use more multi-valued semantic selectors, for example, class, ID or string.

Perhaps you are already using some of the above combinators and selectors — perhaps correctly or not — but a reminder in which cases they are more convenient than class or ID will not hurt. Even the best of us are often mistaken in such things.

Source: https://habr.com/ru/post/123949/


All Articles