pseudo classes – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Fri, 04 Feb 2022 15:26:20 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 pseudo classes – CSS-Tricks https://css-tricks.com 32 32 45537868 Chromium spelling and grammar features https://css-tricks.com/chromium-spelling-and-grammar-features/ https://css-tricks.com/chromium-spelling-and-grammar-features/#respond Tue, 29 Jun 2021 20:25:00 +0000 https://css-tricks.com/?p=343260 Delan Azabani digs into the (hopefully) coming soon ::spelling-error and ::grammar-error pseudo selectors in CSS. Design control is always nice. Hey, if we can style scrollbars and style selected text, why not this?

The squiggly lines that indicate possible spelling or grammar errors


Chromium spelling and grammar features originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Delan Azabani digs into the (hopefully) coming soon ::spelling-error and ::grammar-error pseudo selectors in CSS. Design control is always nice. Hey, if we can style scrollbars and style selected text, why not this?

The squiggly lines that indicate possible spelling or grammar errors have been a staple of word processing on computers for decades. But on the web, these indicators are powered by the browser, which doesn’t always have the information needed to place and render them most appropriately. For example, authors might want to provide their own grammar checker (placement), or tweak colors to improve contrast (rendering).

To address this, the CSS pseudo and text decoration specs have defined new pseudo-elements ::spelling-error and ::grammar-error, allowing authors to style those indicators, and new text-decoration-line values spelling-error and grammar-error, allowing authors to mark up their text with the same kind of decorations as native indicators.

This is a unique post too, as Delan is literally the person implementing the feature in the browser. So there is all sorts of deep-in-the-weeds stuff about how complex all this is and what all the considerations are. Kinda like, ya know, web development. Love to see this. I’ve long felt that it’s weird there is seemingly such little communication between browser engineers and website authors, despite the latter being a literal consumer of the former’s work.

There is a part 2 now. Still very early days.

To Shared LinkPermalink on CSS-Tricks


Chromium spelling and grammar features originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/chromium-spelling-and-grammar-features/feed/ 0 343260
:nth-child Between Two Fixed Indexes https://css-tricks.com/nth-child-between-two-fixed-indexes/ https://css-tricks.com/nth-child-between-two-fixed-indexes/#comments Tue, 29 Jun 2021 14:37:21 +0000 https://css-tricks.com/?p=342736 I needed to select some elements between two fixed indexes the other day — like literally the second through fifth elements. Ironically, I have a whole post on “Useful :nth-child Recipes” but this wasn’t one of them.

The answer, it …


:nth-child Between Two Fixed Indexes originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I needed to select some elements between two fixed indexes the other day — like literally the second through fifth elements. Ironically, I have a whole post on “Useful :nth-child Recipes” but this wasn’t one of them.

The answer, it turns out, isn’t that complicated. But it did twist my brain a little bit.

Say you want to select all divs from the second one and beyond:

div:nth-child(n + 2) {

}
/* [ ]  [x]  [x]  [x]  [x]  [x]  [x]  [x], etc. */

That makes logical sense to me. If n is 0, the expression is 2, and n increments upwards from there and selects everything beyond it.

But then how do you “stop” the selecting at a specific index? Like…

/* Not real */
div:nth-child(minmax(2, 5)) {

}
/* [ ]  [x]  [x]  [x]  [x]  [x]  [ ]  [ ], etc. */

Well, we can do the opposite thing, selecting only the first set of elements then stopping (constraining in the other direction) by reversing the value of n.

div:nth-child(-n + 6) {

}
/* [x]  [x]  [x]  [x]  [x]  [ ]  [ ]  [ ], etc. */

That will select the the first five elements and then stop because, as n gets bigger, the expression value goes to 0 and into negative numbers.

So, the CSS trick here is to combine both of those :nth-child expressions.

We know that CSS pseudo-selectors are additive in the sense that they must both be true in order to select them.

a:first-child:hover {
  /* selects the <a> if it is BOTH the first child and in a hover state */
}

To accomplish the idea of “2 and over” and “5 and under” we chain the pseudo-selectors:

div:nth-child(n + 2):nth-child(-n + 6) {
  background: green;
}

That’ll do:

The part that twisted my brain was thinking about “additive” pseudo-selectors. I was thinking that selecting “2 and up” would do just that, and “5 and under” would do just that, and those things combined meant “all elements.” But that’s just wrong thinking. It’s the conditions that are additive, meaning that every element must meet both conditions.

If you found this confusing like I did, wait until you check out Quanity Queries. By nesting a lot of nth-style pseudo-selectors, you can build logic that, for example, only selects elements depending on how many of them are in the DOM.

div:nth-last-child(n+2):nth-last-child(-n+5):first-child, 
div:nth-last-child(n+2):nth-last-child(-n+5):first-child ~ div {
  /* Only select if there are at least 2 and at most 5 */
}

Una broke this down even further for us a while back.


:nth-child Between Two Fixed Indexes originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/nth-child-between-two-fixed-indexes/feed/ 6 342736
Custom State Pseudo-Classes in Chrome https://css-tricks.com/custom-state-pseudo-classes-in-chrome/ https://css-tricks.com/custom-state-pseudo-classes-in-chrome/#comments Thu, 06 May 2021 14:28:53 +0000 https://css-tricks.com/?p=339586 There is an increasing number of “custom” features on the web platform. We have custom properties (--my-property), custom elements (<my-element>), and custom events (new CustomEvent('myEvent')). At one point, we might even get custom media


Custom State Pseudo-Classes in Chrome originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There is an increasing number of “custom” features on the web platform. We have custom properties (--my-property), custom elements (<my-element>), and custom events (new CustomEvent('myEvent')). At one point, we might even get custom media queries (@media (--my-media)).

But that’s not all! You might have missed it because it wasn’t mentioned in Google’s “New in Chrome 90” article (to be fair, declarative shadow DOM stole the show in this release), but Chrome just added support for yet another “custom” feature: custom state pseudo-classes (:--my-state).

Built-in states

Before talking about custom states, let’s take a quick look at the built-in states that are defined for built-in HTML elements. The CSS Selectors module and the “Pseudo-classes” section of the HTML Standard specify a number of pseudo-classes that can be used to match elements in different states. The following pseudo-classes are all widely supported in today’s browsers:

User action
:hover the mouse cursor hovers over the element
:active the element is being activated by the user
:focus the element has the focus
:focus-within the element has or contains the focus
Location
:visited the link has been visited by the user
:target the element is targeted by the page URL’s fragment
Input
:disabled the form element is disabled
:placeholder-shown the input element is showing placeholder text
:checked the checkbox or radio button is selected
:invalid the form element’s value is invalid
:out-of-range the input element’s value is outside the specificed range
:-webkit-autofill the input element has been autofilled by the browser
Other
:defined the custom element has been registered

Note: For brevity, some pseudo-classes have been omitted, and some descriptions don’t mention every possible use-case.

Custom states

Like built-in elements, custom elements can have different states. A web page that uses a custom element may want to style these states. The custom element could expose its states via CSS classes (class attribute) on its host element, but that’s considered an anti-pattern.

Chrome now supports an API for adding internal states to custom elements. These custom states are exposed to the outer page via custom state pseudo-classes. For example, a page that uses a <live-score> element can declare styles for that element’s custom --loading state.

live-score {
  /* default styles for this element */
}

live-score:--loading {
  /* styles for when new content is loading */
}

Let’s add a --checked state to a <labeled-checkbox> element

The Custom State Pseudo Class specification contains a complete code example, which I will use to explain the API. The JavaScript portion of this feature is located in the custom element‘s class definition. In the constructor, an “element internals” object is created for the custom element. Then, custom states can be set and unset on the internal states object.

Note that the ElementInternals API ensures that the custom states are read-only to the outside. In other words, the outer page cannot modify the custom element’s internal states.

class LabeledCheckbox extends HTMLElement {
  constructor() {
    super();

    // 1. instantiate the element’s “internals”
    this._internals = this.attachInternals();

    // (other code)
  }

  // 2. toggle a custom state
  set checked(flag) {
    if (flag) {
      this._internals.states.add("--checked");
    } else {
      this._internals.states.delete("--checked");
    }
  }

  // (other code)
}

The web page can now style the custom element’s internal states via custom pseudo-classes of the same name. In our example, the --checked state is exposed via the :--checked pseudo-class.

labeled-checkbox {
  /* styles for the default state */
}

labeled-checkbox:--checked {
  /* styles for the --checked state */
}
Try the demo in Chrome

This feature is not (yet) a standard

Browser vendors have been debating for the past three years how to expose the internal states of custom elements via custom pseudo-classes. Google’s Custom State Pseudo Class specification remains an “unofficial draft” hosted by WICG. The feature underwent a design review at the W3C TAG and has been handed over to the CSS Working Group. In Chrome’s ”intent to ship” discussion, Mounir Lamouri wrote this:

It looks like this feature has good support. It sounds that it may be hard for web developers to benefit from it as long as it’s not widely shipped, but hopefully Firefox and Safari will follow and implement it too. Someone has to implement it first, and given that there are no foreseeable backward incompatible changes, it sounds safe to go first.

We now have to wait for the implementations in Firefox and Safari. The browser bugs have been filed (Mozilla #1588763 and WebKit #215911) but have not received much attention yet.


Custom State Pseudo-Classes in Chrome originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/custom-state-pseudo-classes-in-chrome/feed/ 1 339586
CSS :is() and :where() are coming to browsers https://css-tricks.com/css-is-and-where-are-coming-to-browsers/ Wed, 10 Jun 2020 14:45:00 +0000 https://css-tricks.com/?p=312524 Šime Vidas with the lowdown on what these pseudo-selectors are and why they will be useful:

  • :is() is to reduce repetition¹ of parts of comma-separated selectors.
  • :where() is the same, but nothing inside it affects specificity. The example of


CSS :is() and :where() are coming to browsers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Šime Vidas with the lowdown on what these pseudo-selectors are and why they will be useful:

  • :is() is to reduce repetition¹ of parts of comma-separated selectors.
  • :where() is the same, but nothing inside it affects specificity. The example of wrapping :where(:not()) is really great, as now there is a way to use :not() without bumping up the selector weight in a way you very likely don’t want.
  1. This is something that CSS preprocessors are good at (via nesting). Another nice little example of community-built tech pushing forward and native tech coming up later to help once the idea is fleshed out.

To Shared LinkPermalink on CSS-Tricks


CSS :is() and :where() are coming to browsers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
312524
Meet the Pseudo Class Selectors https://css-tricks.com/pseudo-class-selectors/ https://css-tricks.com/pseudo-class-selectors/#comments Wed, 17 Mar 2010 11:55:23 +0000 http://css-tricks.com/?p=5762 Pseudo class selectors are CSS selectors with a colon preceding them. You are probably very familiar with a few of them. Like hover:

a:hover {
  /* Yep, hover is a pseudo class */
}

They are immensely useful in a …


Meet the Pseudo Class Selectors originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Pseudo class selectors are CSS selectors with a colon preceding them. You are probably very familiar with a few of them. Like hover:

a:hover {
  /* Yep, hover is a pseudo class */
}

They are immensely useful in a variety of situations. Some of them are CSS3, some CSS2… it depends on each particular one. Outside of IE, they have great browser support. In IE land, even IE8, support is pretty barren. However, the IE9 preview has full support for them. The link-related ones work but not much else. Let’s take a brief look at each one of them. Don’t worry, there aren’t that many.

:link – Perhaps the most confusion-causing link-related pseudo-selector. Aren’t all <a> links? Well not if they don’t have an href attribute. This selects only those that do, thus is essentially the same as a[href]. This selector will become a lot more useful should any-element linking become reality.

:visited – Selects links that have already been visited by the current browser.

:hover – When the mouse cursor rolls over a link, that link is in its hover state and this will select it.

:active – Selects the link while it is being activated (being clicked on or otherwise activated). For example, for the “pressed” state of a button-style link or to make all links feel more button-like.

There is a fun technique to remember all the link pseudo-class selectors. Look at the first letter of each: LVHA … LOVE HATE.

:focus – Defining hover styles for links is great, but it doesn’t help out those who used keyboard navigation to get to the link. :focus will select links that are the current focus of the keyboard. This is not limited to links, but can be used (and really should be used) on inputs and textareas as well. Some would tell you to define a :focus style for anything that has a :hover style.

Form with a text input in focus. Yellow background is a focus style.
Form with a text input in focus. Yellow background is a focus style.

:target – The target pseudo class is used in conjunction with IDs, and match when the hash tag in the current URL matches that ID. So if you are at URL www.yoursite.com/#home then the selector #home:target will match. That can be extremely powerful. For example, you can create a tabbed area where the tabs link to hash tags and then the panels “activate” by matching :target selectors and (for example) using z-index to move to the top.

:enabled – Selects inputs that are in the default state of enabled and ready to be used.

:disabled – Selects inputs that have the disabled attribute. A lot of browsers will make the input a faded out gray, you can control that with this selector.

Form using the :disabled attribute.

:checked – Selects checkboxes that are, wait for it, checked.

:indeterminate – Selects radio buttons that are in the purgatory state of neither chosen or unchosen (like when a page loads with radio button choices but no default is set).

Set of radio buttons in purgatory. Or more accurately, in their :indeterminate status.

:required – Selects inputs with the required attribute.
:optional – Selects inputs that do not have the required attribute.

:read-only / :read-write – Selects elements based on a combination of readonly and disabled attriutes.

Position/Number-based pseudo class selectors

:root – Selects the element that is at the root of the document. Almost certainly will select the element, unless you are specifically working in some weird environment that somehow also allows CSS. Perhaps XML.

:first-child – Selects the first element within a parent.

:last-child – Selects the last element within a parent.

:nth-child() – Selects elements based on a simple provided algebraic expression (e.g. “2n” or “4n-1”). Has the ability to do things like select even/odd elements, “every third”, “the first five”, and things like that. Covered in more detail here with a tester tool.

:nth-of-type() – Works like :nth-child, but used in places where the elements at the same level are of different types. Like if inside a div you had a number of paragraphs and a number of images. You wanted to select all the odd images. :nth-child won’t work there, you’d use div img:nth-of-type(odd). Particularly useful when working with definition lists and their alternating <dt> and <dd> elements.

:first-of-type – Selects the first element of this type within any parent. So if you have two divs, each had within it a paragraph, image, paragraph, image. Then div img:first-of-type would select the first image inside the first div and the first image inside the second div.

:last-of-type – Same as above, only would select the last image inside the first div and the last image inside the second div.

:nth-last-of-type() – Works like :nth-of-type, but it counts up from the bottom instead of the top.

:nth-last-child() – Works like :nth-child, but it counts up from the bottom instead of the top.

:only-of-type – Selects only if the element is the only one of its kind within the current parent.

Position/Number-based pseudo class selectors

Relational pseudo class selectors

:not() – Removes elements from an existing matched set that match the selector inside the parameter of :not(). So for example, all divs except those with a class of “music” = div:not(.music). The spec says that :not selectors cannot be nested, but they can be chained. Some browsers (Firefox) also support comma-separated selectors as the selector parameter, although chaining them would be a far safter bet. Also useful in conjunction with attribute selectors, e.g. input:not([disabled]).

:empty – Selects elements which contain no text and no child elements. Like:

::first-letter – Selects the first letter of the text in the element. Typical use: drop caps.

::first-line – Selects the first line of text in the element. Typical use: setting the first sentence in small caps as a typographical eye-catcher/lead-in.

:lang – This pseudo selector is in the CSS3 spec but is only implemented in IE 8+. Will match anything that either has or is a descendant of an element with a matching lang attribute. For example, :lang(fr) will match any paragraph, even without a lang attribute, if the parent body had lang="fr" as an attribute.

Quick note

You can chain pseudo selectors just like you can chain class and ID selectors. This is particularly useful here while we are looking at :first-letter and :first-line. You probably wouldn’t want to drop cap every single paragraph on the page, but just the first one, so, p:first-child:first-letter { }

Dropcap using :first-letter, which enlarges the font size and floats to the left.

::before – Is able to add content before a certain element. For example, adding an opening quote before a blockquote or perhaps an preceding image to set apart a particular paragraph.

::after – Is able to add content after a certain element. For example, a closing quote to a blockquote. Also used commonly for the clearfix, where an empty space is added after the element which clears the float without any need for extra HTML markup.

Pseudo Elements vs Pseudo Classes

The above two selectors are appropriately called pseudo “elements” (not selectors) because they don’t select any “real” element that exists on the page. This goes for these two, as well as the previous sections ::first-letter and ::first-line. Make sense? Like the first letter that ::first-letter selects isn’t an element all to itself, it’s just a part of an existing element, hence, pseudo element.

Selector StyleNameDoesSpecificity
::pseudo elementselects/creates some actual content0 0 0 1
:pseudo classselects elements in certain conditions0 0 1 0

Tag Qualification

These selectors can be tag-qualified, meaning they will only apply if both the element (tag) and selector match. For instance:

p:first-child {
  color: red;
}

That will only match if the first child of another element is a <p>. If it’s not, it won’t match.

Deprecated

:contains() – As far as I know, this is gone. The current CSS3 spec has removed it. I don’t know the story, let me know if you do. At a glance, it looks ridiculously useful (being able to select objects based on the textual content they contain). It may be because of problems, or having content in selectors being undesirable. My preference would be to have it select by elements rather than text, like p:contains(img), but alas, no such luck.

Update: There is a :has() selector now!

::selection – Allows the changing of style of selected text. It was drafted for CSS Selectors Level 3 but removed before it reached the Recommendation status. Despite this, it’s implemented in some browsers, which will probably retain experimental support for it. For Firefox, you can use ::-moz-selection. More information here.

Update: ::selection is totally standard now, go ahead and use it!

jQuery Usage

jQuery can use all of these in its selectors, which is awesome. Even awesomer, jQuery has additional pseudo class selectors available.

:first – Matches the first instance of the already matched set. This is different than :nth-child(1) which will only select if the selector matches and it’s the first child. With :first, the selector matches, then it takes the first one it finds regardless of child position.

:eq()jQuery doesn’t support :nth-of-type as a part of it’s selector engine, but this is very similar.It does now. This selects the Xth element from the already-matched set. It’s also zero-indexed (0 is the first element) unlike :nth-child in which the first element is 1.

:contains('text') – This is removed from CSS, but it works in jQuery.

:lt() – The same as :nth-child(-n+X), as in it selects the “first X elements”

:gt() – The same as :nth-child(n+X), as in it selects everything except the “first (X-1) elements”

:even – The same as :nth-child(even) or :nth-child(2n)

:odd – The same as :nth-child(odd) or :nth-child(2n+1)

:has() – Tests if the element has a descendant of a certain selector before matching, like :has("div.intro").

There are actually a whole bunch more, and all of them are clever and useful (or at least an improvement on readability) See the selector documentation for more.

jQuery can’t really help you with pseudo elements like ::before and ::after, but you can access their values in some browsers. E.g if a div had some ::before generated content, you could get the value like:

var div = document.querySelector("div");

var content = window
  .getComputedStyle(div, '::before')
  .getPropertyValue('content');

Specificity

Class selectors and pseudo class selectors have the same specificity weight. Pseudo elements have the specificity of an element selector.

li             {} /* specificity = 0,0,0,1 */
li:first-child {} /* specificity = 0,0,1,1 */
li:first-line  {} /* specificity = 0,0,0,2 */
li.red         {} /* specificity = 0,0,1,1 */

Typically they are used in conjunction or listed afterwards in CSS anyway, so hopefully it won’t cause too many problems…

ul li.friend { margin: 0 0 5px 0; }
ul li:last-child { margin: 0; }

In that case the zeroing out of the margin would work (assuming it matched the same element), but only because the zeroing out is listed second (they have the same specificity). So… watch for that.


Meet the Pseudo Class Selectors originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/pseudo-class-selectors/feed/ 69 5762