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

scss-root-selectors

v1.0.0

Published

Concise, DRY, maintainable and scalable SCSS solution for styling large scale projects

Downloads

24

Readme

##Express a conditional states/modes with regard to the root state (class)

###Motivation

Components have various modes which are turned on/off by toggling class names on the root node. Express SCSS concisely and refer to root node modes, without losing the scope you style and maintain the same DOM hierarchy inside the SCSS file.


Given a simple component CSS with some nesting:

.comp-root-selector {
  > .child {
    > .another-child {
      color: blue;
    }
  }
}

.another-child should get color: orange; when .comp-root-selector is appended with an additional class: .special. Let's examine with using the built in ancestor selector (&):

.comp-root-selector {
  > .child {
    > .another-child {
      color: blue;
      
      .special & {
        color: orange
      }
    }
  }
}

It will yield the following CSS, where .special is an ancestor or .comp-root-selector. Note the space between them:

.comp-root-selector > .child > .another-child {
  color: blue;
}

.special .comp-root-selector > .child > .another-child {
  color: orange;
}

If you need to have it on the same root selector, use the library's mixin:

.comp-root-selector {
  > .child {
    > .another-child {
      color: blue;
      
      @include when-root-has-class(special) {
        color: orange;
      }
    }
  }
}

Will yield the following (desired) CSS. Note: there is no space in .special.comp-root-selector.

.comp-root-selector > .child > .another-child {
  color: blue;
}
.special.comp-root-selector > .child > .another-child {
  color: orange;
}

Similarly, the following SCSS mixins are available as part of the library: Classes modes for a selector:

  • when-root-has-class($class-name): when the specified classes is authored on the root level.
  • when-root-has-any-class($class-names): one of the specified classes (one or many) is authored on the root level
  • when-root-has-all-classes($class-names): all specified classes (one or many) are authored on the root level

Pseudo class modes for a selector:

  • when-root-has-pseudo-class($pseudo-class): The specified pseudo class is authored on the root level
  • when-root-has-all-pseudo-classes($pseudo-classes): all specified pseudo classes are authored on the root level
  • when-root-has-any-pseudo-classes($pseudo-class-names): any of the specified pseudo classes are authored on the root level.

Attribute modes for a selector:

  • when-root-has-attr($pseudo-class): The specified attribute selector is authored on the root level
  • when-root-has-all-attrs($pseudo-classes): all specified attribute selector are authored on the root level
  • when-root-has-any-attrs($pseudo-class-names): any of the specified attribute selector are authored on the root level.
  • create-attr-selector($name, $value): a shorthand for the [name="value"] attribute selector string. use as a constructor for convenience

Any combination:

  • when-root-has-all($class-names, $pseudo-class-names, $attr-selectors): all specified combination of class names, pseudo class names and attribute selectors, authored on the root level.
  • when-root-has-any($class-names, $pseudo-class-names, $attr-selectors): any of the specified combination of class names/pseudo class names/attribute selectors are authored on the root level.

Advanced: Ancestor pseudo conditions:

  • when-parent-has-pseudo($pseudo-classes): if previous part of selector has the specified pseudo classes, apply the styling.
  • when-ancestor-has-pseudo($pseudo-classes, $levels): when an ancestor up the selector has the specified pseudo classes, apply the styling. The ancestor is specified by an number of levels up the selector.
  • see root selector helpers

##Example: A custom checkbox

  • Specified colors for various different modes (regular / hover / selected)
  • Needs to have a "beautiful" mode which specifies different styling. (See Pen by @eitaneitan on CodePen.)
<label class="control-checkbox">
  <input type="checkbox" class="input" />
  <div class="content"></div>
</label>

.control-checkbox {
  display: inline-block;
  cursor: pointer;

  > .input {
    display: none;

    + .content {
      width: 28px;
      height: 28px;
      background-color: red;
      border: solid 3px blue;
    }

    &:checked + .content {
      background-color: green;
    }
  }

  &:hover > .input + .content {
    background-color: yellow;
  }

  &.beautiful {
    > .input {
      + .content {
        background-color: cyan;
        border-color: lime;
        border-radius: 50%;
      }
      
      &:checked + .content {
        background-color: orange;
      }
    }
    
    &:hover {
      > .input + .content {
        background-color: grey;
      }
    }
  }
}

A better approach: DRY, concise, extensible, refactorable, DOM-like structure:

.control-checkbox {
  display: inline-block;
  cursor: pointer;

  > .input {
    display: none;

    + .content {
      width: 28px;
      height: 28px;
      background-color: red;
      border: solid 3px blue;
      
      @include when-parent-has-pseudo(checked) {
        background-color: green;        
      }
      
      @include when-root-has-pseudo-class(hover) {
        background-color: yellow;        
      }
      
      @include when-root-has-class(beautiful) {
        background-color: cyan;
        border-radius: 50%;
        border-color: lime;
        
        @include when-parent-has-pseudo(checked) {
          background-color: orange;
        }
        
        @include when-root-has-pseudo-class(hover) {
          background-color: grey;          
        }
      }
    }
  }
}

Compiled CSS Code:

.control-checkbox {
  display: inline-block;
  cursor: pointer;
}
.control-checkbox > .input {
  display: none;
}
.control-checkbox > .input + .content {
  width: 28px;
  height: 28px;
  background-color: red;
  border: solid 3px blue;
}
.control-checkbox > .input:checked + .content {
  background-color: green;
}
.control-checkbox:hover > .input + .content {
  background-color: yellow;
}
.beautiful.control-checkbox > .input + .content {
  background-color: cyan;
  border-radius: 50%;
  border-color: lime;
}
.beautiful.control-checkbox > .input:checked + .content {
  background-color: orange;
}
.beautiful.control-checkbox:hover > .input + .content {
  background-color: grey;
}

##Recommended scss-lint configuration It really assists with getting things in order:

  DeclarationOrder:
    enabled: true

  DisableLinterReason:
    enabled: true

  DuplicateProperty:
    enabled: true

  SingleLinePerProperty:
    enabled: true
    allow_single_line_rule_sets: false

  SingleLinePerSelector:
    enabled: true

  MergeableSelector:
    enabled: true
    force_nesting: true

  EmptyRule:
    enabled: true