{"id":254901,"date":"2017-05-17T05:18:16","date_gmt":"2017-05-17T12:18:16","guid":{"rendered":"http:\/\/css-tricks.com\/?p=254901"},"modified":"2017-05-24T08:00:14","modified_gmt":"2017-05-24T15:00:14","slug":"extremely-handy-nth-child-recipes-sass-mixins","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/extremely-handy-nth-child-recipes-sass-mixins\/","title":{"rendered":"Some Extremely Handy `:nth-child` Recipes as Sass Mixins"},"content":{"rendered":"
There is no such thing as one-size-fits-all styling. An image gallery with three images might need to be styled differently than an image gallery with twelve. There are some cool tricks that you can use to add some number-based logic to your CSS! Using This post will assume that you have a basic understanding of how the <\/p>\n You may be aware that along with See the Pen 1. Selecting The Last Three<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n Similarly, you can use See the Pen 2. Selecting All But The Last Three<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n The real magic<\/strong> happens when you start combining Continuing with our list example, here is a way to visualize how this works:<\/p>\n See the Pen 3. Chaining Together “first-child” and “last three”<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n Conversely, you can use See the Pen 4. At Least Three Selector<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n Pretty cool, right? But chances are, you’ll want to style more than just the first item in a list. By using the general sibling selector, you can style any list items that follows this first element. Add both selectors separated by a comma, and you can select all elements. <\/p>\n See the Pen 5. At Least Four Selector<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n This leads to a lot of interesting possibilities! You also don’t need to just limit yourself to counting the total number of elements. By chaining together One real world use case that this technique can be used for is styling dropdown menus that have been automatically generated by a CMS. For an example, let’s take a look at the code generated by the WordPress See the Pen WordPress Menu nth-child example<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n This looks pretty standard. Hover over the Members<\/strong> menu item, and notice the sub-menu items. <\/p>\n Now, let’s look at the same menu with a few more members added:<\/p>\n See the Pen WordPress Menu nth-child example, more children<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n Whoa! The styling that worked fine for four items doesn’t scale well to twelve. By applying the previous example, you can style the WordPress default menu purely in the stylesheet: no need to write a custom filter to change the class depending on the number of menu items: you can keep the styling in the stylesheet.<\/p>\n See the Pen WordPress Menu nth-child example, compact<\/a> by Adam Giese (@AdamGiese<\/a>) on CodePen<\/a>.<\/p>\n Here are some other possible use cases.<\/p>\n There are a lot of cool things that you can do with Another consideration is whether or not to use I have found that this trick works best when applied to elements with predictable siblings. This is a cool trick, but unfortunately the syntax is a little bit hairy. If you are using Sass, however, you can easily add a layer of abstraction to make it much easier to use! This will make the use of these complex selectors much more readable and intuitive.<\/p>\n Since all of these selectors are based on a single pattern, you can start with a general mixin:<\/p>\n Which would be called in SCSS using something like:<\/p>\n While this is definitely less cluttered than writing pure CSS, you can add another layer of abstraction by defining a few more mixins. Here is an example of how to write an These would be called in the code like this: <\/p>\n Definitely an improvement in readability! You can even chain together mixins by nesting them. <\/p>\n Here<\/a> is a collection of Sass mixins using some complex nth-child logic. <\/p>\n There are some additional features that are currently in the W3C Editor’s Draft that could greatly increase the flexibility of this technique. One of these is the This will style any active list items if there are at least five. You can read more about the selector list here<\/a>. Browser support is currently very limited, however; it is only available on Safari (both iOS and OSX). <\/p>\n:nth-child<\/code> and
:nth-last-child<\/code>, you can get some surprisingly complex information without ever leaving your stylesheet.<\/p>\n
:nth-child<\/code> pseudo-selector works. If you need a quick refresher, Chris has a great post<\/a> covering that topic. <\/p>\n
Writing Complex
:nth-child()<\/code> Selectors<\/h3>\n
:nth-child<\/code> there is the related
:nth-last-child<\/code>. It works exactly the same as
:nth-child<\/code> except that it starts from the end<\/em> of the parent. For example, you can select the first three children<\/em> of a parent by using the selector
:nth-child(-n + 3)<\/code>. You can use
:nth-last-child(-n + 3)<\/code> to select the last<\/em> three. Let’s take a look an unordered list for an example.<\/p>\n
:nth-last-child(n + 4)<\/code> to select all children except<\/em> the last three.<\/p>\n
:nth-last-child<\/code> with
:first-child<\/code>. By using both selectors to see if an element is both the first child of the parent and<\/em> one of the last three elements, you can style the first element of a parent only if<\/em> there are at most three elements. <\/p>\n
li:nth-last-child(-n + 3):first-child {\r\n \/* your styling here *\/\r\n}<\/code><\/pre>\n
li:nth-last-child(n + 4):first-child<\/code> to select the first item of a list that has four or more<\/em> items:<\/p>\n
li:nth-last-child(n + 4):first-child,\r\nli:nth-last-child(n + 4):first-child ~ li {\r\n \/* your styling here *\/\r\n}<\/code><\/pre>\n
:first-child<\/code> and
:nth-last child<\/code>, you can check if any valid
:nth-child<\/code> expression applies to the total number of elements. You can write styling if there are a total number of odd children, if there are exactly seven children, or if there are
3n + 2<\/code> children. <\/p>\n
wp_nav_menu()<\/code> function, cleaned up for readability:<\/p>\n
\n
Limitations<\/h3>\n
:nth-child<\/code>. However, there are some limitations. For example, you are not able to style the parent, only the children. You can’t add any styling for a
ul<\/code> by the number of
li<\/code> elements it contains.<\/p>\n
:nth-child<\/code> or
:nth-of-type<\/code>. Using
:nth-child<\/code> will select all of the elements, which may or may not be what you want. For example, if you want to add styling to a
.post-content<\/code> based on the number of paragraphs, you would want to use
p:nth-of-type<\/code>. Unfortunately, using this method you would only be able to style children after (and including) the first paragraph tag. If there were an
h2<\/code> tag at the beginning of the content, you would not be able to style the heading based on the number of
p<\/code> tags. Additionally,
nth-of-type<\/code> only works on elements: you would not be able to check the quantity of a specific class. <\/p>\n
li<\/code> is a perfect candidate, since they are the only valid children of
ul<\/code> and
ol<\/code>. Automatically generated content can also work well.<\/p>\n
Abstractions<\/h3>\n
@mixin has-nth($expression, $element: '*') {\r\n &:nth-last-child(#{$expression}):first-child,\r\n &:nth-last-child(#{$expression}):first-child ~ #{$element} {\r\n @content;\r\n }\r\n}<\/code><\/pre>\n
li {\r\n @include has-nth('n + 4', 'li') { \/\/four or more\r\n \/* your styling here *\/\r\n }\r\n}<\/code><\/pre>\n
at-least<\/code> mixin:<\/p>\n
@mixin at-least($quantity, $element: '*') {\r\n @include has-nth('n + #{$quantity}', $element) {\r\n @content;\r\n }\r\n}<\/code><\/pre>\n
li {\r\n @include at-least(4, 'li') { \/\/ four or more\r\n \/\/ styling goes here...\r\n }\r\n}<\/code><\/pre>\n
Future Selectors<\/h3>\n
selector list<\/code> argument for nth-child. This works by adding an additional optional argument to the
nth-child<\/code> selector. This works similarly to how the
nth-of-type<\/code> works, except that it works for any<\/em> selector, not just elements. For example, of you could use the selector
li:nth-child(odd of .active)<\/code> to style every other list item with a class of
active<\/code>. Using this feature, we can detect the quantity of a specific class: for example:<\/p>\n
li.active:nth-last-child(n + 5 of .active).first-child,\r\nli:nth-last-child(n + 5 of .active).first-child ~ li.active {\r\n \/* styling goes here... *\/\r\n}<\/code><\/pre>\n