npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

postcss-nested-ancestors

v3.0.0

Published

PostCSS plugin to reference any ancestor selector in nested CSS

Downloads

30,623

Readme

PostCSS Nested ancestors

Build status Npm version Test coverage report

PostCSS plugin to reference any parent ancestor selector in nested CSS.

Getting ancestor selectors

When writing modular nested CSS, & current parent selector is often not enough.

PostCSS Nested ancestors introduces ^& selector which let you reference any parent ancestor selector with an easy and customizable interface.

This plugin should be used before a PostCSS rules unwrapper like postcss-nested.

See PostCSS docs for examples for your environment.

Ancestor selectors schema

    .level-1 {
|   |   .level-2 {
|   |   |   .level-3 {
|   |   |   |   .level-4 {
|   |   |   |   |
|   |   |   |   --- & {}        /*      & = ".level-1 .level-2 .level-3 .level-4" */
|   |   |   ------- ^& {}       /*     ^& = ".level-1 .level-2 .level-3"          */
|   |   ----------- ^^& {}      /*    ^^& = ".level-1 .level-2"                   */
|   --------------- ^^^& {}     /*   ^^^& = ".level-1"                            */
------------------- ^^^^& {}    /*  ^^^^& = ""                                    */
                }
            }
        }
    }

A real example

/* Without postcss-nested-ancestors */
.MyComponent
    &-part{}
    &:hover {
        > .MyComponent-part {} /* Must manually repeat ".MyComponent" for each child */
    }
}

/* With postcss-nested-ancestors */
.MyComponent
    &-part{}
    &:hover {
        > ^&-part {} /* Skip ":hover" inheritance here */
    }
}

/* After postcss-nested-ancestors */
.MyComponent {
    &-part{}
    &:hover {
        > .MyComponent-part {}
}

/* After postcss-nested */
.MyComponent {}
.MyComponent-part {}
.MyComponent:hover {}
.MyComponent:hover > .MyComponent-part {} /* No ":hover" inheritance here! */

Why?

Currently another plugin - postcss-current-selector - has tried to solve the problem of referencing ancestors selector. It works great, but its approach involves assigning ancestor selectors to special variables to be later processed by a further postcss plugin postcss-simple-vars.

PostCSS Nested ancestors instead replaces special ancestor selectors, makes no use of variable assignment and produces an output ready to be unwrapped with postcss-nested.

Installation

$ npm install --save-dev postcss postcss-nested-ancestors

Usage

postcss([require('postcss-nested-ancestors')]);

Options

placeholder

Type: string Default: ^&

Ancestor selector pattern (utility option to automatically set both levelSymbol and parentSymbol)

levelSymbol

Type: string Default: ^

Define ancestor selector fragment relative to the matching nesting level

parentSymbol

Type: string Default: &

Ancestor selector base symbol

replaceDeclarations (experimental)

Type: boolean Default: false

If this is true then this plugin will look through your declaration values for the placeholder symbol and replace them with specified selector.

An use case for this if enabling postcss-ref to work with dynamic @ref selectors. Read discussion here.

/* Before */
.foo {
  &:last-child {
    border-top: ref(^&, border-bottom);
  }
}

/* After PostCSS Nested ancestors and PostCSS Nested */
.foo {
}

.foo:last-child {
  border-top: ref(.foo, border-bottom);
}

Known issues

Multiple ancestor placeholders in same selector

This plugin currently fails when trying to replace more than one different ancestor placeholder in a single rule selector. This scenario has not been considered in order to not bloat the code with a remote use case.

More precisely, all ancestor placeholders are replaced, but processed as if they where the equal to the first ancestor placeholder found in selector.

In general, do not use more than one ancestor placeholder in a single rule selector. Anyway, this use case can be rewritten by splitting the selectors in multiple nested rules (see edge case 2).

Edge case 1 (success)

/* 2 equal ancestor placeholders in single rule selector */
.a {
  &:hover {
    ^&^&-b {
    }
  }
}

/* Output: It works but casts a warning */
.a {
  &:hover {
    .a.a-b {
    }
  }
}

Edge case 2 (failing)

/* 2 different ancestor placeholders in single rule selector */
.a {
  &-b {
    &:hover {
      /* Will be processed as ^&^&-c{}, sorry! */
      ^&^^&-c {
      }
    }
  }
}

/* Wrong output: All placeholder replaced with the value of the first one */
.a {
  &-b {
    &:hover {
      /* Expected output: .a-b.a-c{}*/
      .a-b.a-b-c {
      }
    }
  }
}

/* This use case can be rewritten as: */
.a {
  &-b {
    &:hover {
      ^& {
        &^^^&-c {
        }
      }
    }
  }
}

Replace declaration values in complex nesting scenarios

replaceDeclarations options used in a complex nesting scenario might have undesired outputs because of the different nature of CSS selectors and and declaration values.

In general, avoid replacing declaration values when inside a rule with multiple selectors (but why should you?). In other words don't get yourself into trouble!

Here is an example of what you don't want to do.

/* Don't replace declaration value inside multiple selector rules */
.a1,
.a2 {
  &:hover {
    &:before {
      content: '^^&';
    }
  }
}

/* Output */
.a1,
.a2 {
  &:hover {
    &:before {
      content: '.a1,.a2';
    }
  }
}

Contributing

Contributions are super welcome, but please follow the conventions below if you want to do a pull request:

  • Create a new branch and make the pull request from that branch
  • Each pull request for a single feature or bug fix
  • If you are planning on doing something big, please discuss first with @toomuchdesign about it
  • Update tests (test.js) covering new features

Todo's

  • Better comment source code