The CSS visible selector is a powerful tool that allows you to target elements that are visible on the page. This is particularly useful for hiding or showing elements based on certain conditions.
To use the CSS visible selector, you need to understand how it works. The visible selector is used in combination with the :not pseudo-class to exclude elements that are hidden by default.
The visible selector is not the same as the :visible pseudo-class, which is used to select elements that are visible and not hidden by default. The :visible pseudo-class is more commonly used in conjunction with the :not pseudo-class to exclude elements that are hidden.
CSS Selectors
CSS selectors are the backbone of CSS, allowing you to target specific elements on a webpage.
There are several types of CSS selectors, including element selectors, which select elements by their tag name, such as `h1` or `p`.
ID selectors are used to select elements with a unique ID, denoted by a `#` symbol, like `#header`.
Class selectors, on the other hand, select elements with a specific class, denoted by a `.` symbol, like `.nav`.
Attribute selectors can be used to select elements based on their attributes, such as `a[href="https://www.example.com"]`.
These selectors can be combined using logical operators, like `div.error` to select elements that are both `div` and have the class `error`.
The Directionality :dir()
The Directionality :dir() allows you to write selectors that represent an element based on its directionality as determined by the document language.
This pseudo-class is particularly useful in languages that read from right to left, such as Hebrew and Arabic. For example, in HTML, the directionality of an element inherits from its closest ancestor with a valid dir attribute.
The :dir() pseudo-class does not select based on stylistic states, so the CSS direction property does not affect whether it matches. This means you can use it to select elements based on their inherent directionality, not just their visual representation.
The pseudo-class :dir(ltr) represents an element that has a directionality of left-to-right (ltr), while :dir(rtl) represents an element that has a directionality of right-to-left (rtl).
Nth-last-col()
The :nth-last-col() pseudo-class is a powerful tool in CSS selectors. It allows you to select a cell element based on its position in a table, relative to the last column.
This pseudo-class uses the notation An+B, where n and B are integers. The algorithm returns a list of elements that meet the specified condition.
The :nth-last-col() pseudo-class is used to determine column membership based on the semantics of the document language. This means that the presentation of the elements is not considered.
A cell element can belong to more than one column, and it is represented by a selector indicating any of those columns. If a cell element does not meet the specified condition, it is not included in the list.
The :nth-last-col() pseudo-class is useful for styling tables in a specific way, such as highlighting a particular column based on its position.
Pseudo-Elements
Pseudo-elements represent elements not directly present in the document tree and are used to create abstractions about the document tree beyond those provided by the document tree.
Pseudo-elements can be used to select portions of the document that don't correspond to a document-language element, such as ranges that don't align to element boundaries or fit within its tree structure.
The ::before and ::after pseudo-elements allow additional content to be inserted before or after the contents of any element.
Pseudo-elements that exist in CSS are defined in CSS Level 2, Level 3, and Level 4 specifications.
The selector ::first-line is equivalent to *::first-line, which selects the ::first-line pseudo-element on every element in the document.
Pseudo-elements can be immediately followed by user action pseudo-classes, representing the pseudo-element only when it's in the corresponding state.
Unless otherwise specified, none of these pseudo-classes will match on the pseudo-element, and only user action pseudo-classes can be compounded with pseudo-elements.
::first-line:not(:focus) does not match anything, as :not() is used to exclude elements that match a specified selector, and :focus is a user action pseudo-class.
::first-line:hover is very different from :hover::first-line, as the former only matches if the first line itself is hovered, whereas the latter matches the first line of any originating element that is hovered.
Combinators
Combinators are a powerful tool in CSS that allow you to select elements based on their relationships with other elements in the document tree.
A descendant combinator expresses a relationship between an element and its ancestor, represented by whitespace separating two compound selectors. For example, "h1 em" represents an em element contained within an h1 element.
You can use descendant combinators to select elements that are grandchildren or later descendants of a specific element, such as "div * p" which represents a p element that is a grandchild or later descendant of a div element.
The next-sibling combinator (+) is used to select elements that share the same parent and are adjacent to each other, ignoring non-element nodes. For example, "h1 + p" represents a p element following an h1 element.
The subsequent-sibling combinator (~) is similar to the next-sibling combinator but allows for elements that are not necessarily adjacent to each other.
Descendant Combinator
The descendant combinator is a powerful tool in CSS selectors. It allows you to describe an element that is a descendant of another element in the document tree.
A descendant combinator is simply whitespace that separates two compound selectors. For example, the selector "A B" represents an element B that is an arbitrary descendant of some ancestor element A.
This can be useful for styling elements that are nested within other elements. For instance, the selector "div p" represents a p element that is a grandchild or later descendant of a div element.
You can also combine descendant combinators with attribute selectors to create more complex selectors. For example, the selector "div p[href]" represents an element that has the href attribute set and is inside a p that is itself inside a div.
The descendant combinator can be used to style elements based on the state or content of their descendants. For example, the selector "has-img" can be used to style an element based on the presence of an img element within it.
By using the descendant combinator, you can create more precise and efficient CSS selectors that help you target the exact elements you want to style.
Subsequent-Sibling Combinator
The subsequent-sibling combinator is made of the "tilde" (U+007E, ~) code point.
This combinator is used to select an element that precedes another element in the document tree, but not necessarily immediately.
Non-element nodes, such as text between elements, are ignored when considering the adjacency of elements.
The elements represented by the two compound selectors must share the same parent in the document tree.
Structural Pseudo-Classes
Structural Pseudo-Classes are used to select elements based on their position in the document tree.
They allow you to target elements that are the first or last child of their parent, or the only child of their parent.
The :first-child pseudo-class selects an element that is the first child of its parent, while the :last-child pseudo-class selects an only child of its parent.
The :nth-child pseudo-class is more complex, selecting an element based on its position in the list of children.
It can be used to select every other element, or every nth element, making it a powerful tool for styling lists and grids.
You can use the :nth-child pseudo-class to select the first, last, or only child of a parent element, depending on the value you provide.
The :nth-child pseudo-class can be used with a value of 2n to select every other element, or a value of 3n to select every third element.
For example, if you have a list of items with class "item", you can use :nth-child(2) to select every other item.
Grid and Flexbox
Grid and Flexbox are two powerful CSS layout systems that help you create responsive and flexible designs. They're particularly useful for building complex layouts, like grids and tables.
In a 2D grid, the double-association of a cell (to its row and column) cannot be represented by parentage in a hierarchical markup language. This means that only one of those associations can be represented hierarchically, with the other being explicitly or implicitly defined in the document language semantics.
To work around this limitation, the column combinator and the :nth-col() and :nth-last-col() pseudo-classes are defined. These pseudo-classes match against row associations instead, allowing you to represent column-based relationships in a column-primary format.
Grid-Structural
Grid-Structural Selectors are a game-changer for layouts that involve rows and columns. They allow you to select elements based on their position in a grid, which is especially useful for complex layouts.
The double-association of a cell in a 2D grid to its row and column cannot be represented by parentage in a hierarchical markup language. This is why we need Grid-Structural Selectors.
In HTML and DocBook, the markup is row-primary, meaning the row associations are represented hierarchically, and columns must be implied. This is where the column combinator and :nth-col() pseudo-class come in.
The column combinator, represented by two pipes (||), determines column membership based on the semantics of the document language only. It doesn't consider how the elements are presented.
The :nth-col(An+B) pseudo-class notation represents a cell element belonging to a column that has An+B-1 columns before it. This is a powerful tool for selecting elements based on their position in a grid.
If a cell element belongs to more than one column, it is represented by a selector indicating any of those columns. This is important to keep in mind when working with complex layouts.
Nth-Child
The :nth-child() pseudo-class is a game-changer for styling lists and tables. It allows you to select elements based on their position within a list of siblings, using the An+B notation.
For example, you can use :nth-child() to address every other row in a table, which can be used to alternate the color of paragraph text in a cycle of four. The first child of an element has an index of 1, and will be matched by :nth-child(2n+1).
The specificity of the :nth-child() pseudo-class is the specificity of a single pseudo-class, plus the specificity of the most specific complex selector in S, if specified. This means that S:nth-child(An+B) and :nth-child(An+B of S) have the same specificity, although they differ in behavior.
If you move the selector outside of the function, it will just select the first three children, but only if they're also "important" list items. This can be useful in certain situations, but it's not the same as using :nth-child().
Using :nth-child() can be more robust than simply selecting every other row, especially if some rows are hidden and not displayed. For example, if you're zebra-stripping a table and some rows are hidden with the [hidden] attribute, :nth-child() will maintain a proper alternating background, regardless of which rows are hidden.
Specificity and Combinations
A selector's specificity is calculated by counting the number of ID selectors, class selectors, attributes selectors, and pseudo-classes in the selector, and ignoring the universal selector.
For example, a selector like #foo.bar is considered more specific than .baz because it has an ID selector and a class selector, while .baz only has a class selector.
When comparing specificities, the one with a larger A value (ID selectors) is more specific, and if the A values are tied, the one with a larger B value (class selectors, attributes selectors, and pseudo-classes) is more specific.
The specificity of a selector can also be affected by pseudo-classes like :is(), :not(), and :has(), which replace their specificity with the most specific complex selector in their argument.
Here's a breakdown of the specificity of some examples:
The :where() pseudo-class is an exception, as it does not contribute to the specificity of the selector, and its specificity is always zero.
Calculating Specificity
Calculating specificity is a crucial step in understanding how CSS selectors work. It's a bit like a game of numbers, where we count the different types of selectors to determine which one is more specific.
The specificity of a selector is calculated by counting the number of ID selectors, class selectors, attribute selectors, and pseudo-classes. For example, if we have a selector like #foo.bar, we would count 1 ID selector, 1 class selector, and 0 pseudo-classes.
In general, the more specific a selector is, the higher its specificity value will be. Specificity is compared by comparing the three components in order: ID selectors, class selectors, and type selectors. If two selectors have the same number of ID selectors, the one with more class selectors is more specific. If they're tied again, the one with more type selectors is more specific.
Here's a quick breakdown of how specificity is calculated:
For example, if we have a selector like #foo.bar, we would count 1 ID selector, 1 class selector, and 0 pseudo-classes, so its specificity would be (1,1,0). If we have a selector like .qux:where(em, #foo#bar#baz), we would count 0 ID selectors, 1 class selector, and 0 pseudo-classes, so its specificity would be (0,1,0).
Some pseudo-classes, like :nth-child() and :not(), have their own specificity rules. For example, :nth-child() counts as one pseudo-class selector plus the specificity of the most specific complex selector in its selector list argument.
The Specificity-Adjustment Where()
The Specificity-Adjustment Where() is a game-changer for CSS selectors. It's a functional pseudo-class that allows you to introduce filters in a selector without affecting its specificity.
Its syntax and functionality are the same as the :is() pseudo-class, but unlike :is(), neither the :where() pseudo-class nor its arguments contribute to the selector's specificity - it's always zero.
This makes it easy to override associated style declarations. By using :where(), authors can explicitly declare their intent, which is useful for future-proofing their code.
Featured Images: pexels.com