Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(S)CSS architecture: alternative backgrounds styling

I'm using 'component' approach to CSS as in SMACSS / ITCSS, I'm still scratching my head about styling sections with alternative (dark) background.

e.g. Stripe has regular (dark text on white) and alternative (white text on dark) sections.

enter image description here

As I understand there are options assuming HTML:

<section class="dark">
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>

Style in context of section, e.g.:

.dark h2, .dark p, .dark btn {
  color: white;
}

But a) context styling is not recommended; b) where does one put the styles? (Harry Roberts argues that in component's file)

Create alternative-colored components with modifiers

And change the HTML, e.g.:

.title--alt-color {color: white;}
.text--alt-color {color: white; }
... 

But a) it doesn't work when you don't know which components will go in there; b) more work of managing HTML.

Maybe there is a better way to handle this?

like image 490
Runnick Avatar asked Mar 22 '17 19:03

Runnick


2 Answers

In a component based approach the ideal way to do this is to have a mapping ready between backgrounds and foreground colours in your style guide. It should be a one to one mapping that should apply to majority of your elements. Have CSS classes defined for the same.

Next have a wrapper container for all your components. Its purpose is to impart text colours to its wrapped components. So the approach is to have a background colour class for the section and then a foreground colour class for the contents that runs applies to wrapper but runs the style through all the contents.

Note: Specific colour overrides can always reside inside your components file for instance using a highlight on some text etc.

The library that is suggested in the comments does the exact same thing. There is a primary and secondary colour in the theme object. The primary applied to the section and secondary is passed on to the individual components as context. I suggest having it passed only to the components' wrapper.

A somewhat clever way to have classes defined is like

t-wrapper-[colorName]

Now this can be generic and colorName can come in as a context to your wrapper based on the background color

Hope this helps. Let me know if this answers what you need or you would need supporting snippets for the same.

like image 72
Ankur Agarwal Avatar answered Oct 24 '22 06:10

Ankur Agarwal


What you're asking for is essentially to style a component within a section based on the section itself. Unfortunately this is impossible with CSS, as there is no parent selector in CSS. However, there is the inherit value, which allows you to style a component based on the rules defined by its parent - perfect for component-driven CSS.

In my opinion, the best way you can go about alternating background styling is to make use of the :nth-of-type pseudo-class on <section>:

section:nth-of-type(2n) {
  background: #464646;
  color: #fff;
}  
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>

Considering :nth-of-type makes use of math to target elements, you can access literally any combination of elements you would like:

// Style every second element, starting with the first element
section:nth-of-type(2n - 1)

// Style every third element, starting with the second element (2, 5, 8, etc.)
section:nth-of-type(3n + 2)

This way, it won't matter whether you're using a component-driven approach or not, as you'll be able to alternate the styling directly off of <section> itself.

Elements that inherit an attribute from internal stylesheets (such as <a> tag colour) will unfortunately still be styled based on the internal stylesheet, rather than rules defined by their parent.

You can get around this by either using context-styling:

section:nth-of-type(n) {
  background: #464646;
  color: #fff;
}

section:nth-of-type(n) a {
  color: #fff;
}
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>

Or alternatively (and preferably) making use of the inherit value to tell every <a> tag to inherit its color from its parent:

section {
  background: #464646;
  color: #fff;
}
a {
  color: inherit;
}
<section>
    <h2>Title</h2>
    <p>Text</p>
    <a href="#" class="btn">Action</a>
</section>

Hope this helps!

like image 30
Obsidian Age Avatar answered Oct 24 '22 05:10

Obsidian Age