Sass nesting multiple classes - css

Alright, so this is what I want to achieve:
.about{
/* some styling */
}
.about,.about-pg{
/* other styling */
}
Using Sass, I figured I could do
.about
/* some styling */
&,.about-pg
/* other styling */
However it compiles to:
.about{
/* some styling */
}
.about,.about .about-pg{
/* other styling */
}
Any clue why and how to solve this?

Use #extend:
.about
/* some styling */
#extend .about-pg
.about-pg
/* other styling */

Related

CSS of nested selector is not being applied to div

I utilised the BEM method and my <div> is showing the css from the Block and Modifier, but not the Element
i.e. the css for c-banner(block) and --warning(modifier) is appearing but not __icon(element).
I know that the color of the modifier is appearing because I tried changing it to another color and it appears on the UI.
Eg:
Currently:
&--warning {
color: #D9822B
}
Edited:
&--warning {
color: black
}
Once changed, the icon of --warning will show up with a black color on the UI.
However, the padding-right of __icon doesn't ever get applied.
c-banner {
/* Block CSS Properties */
&__icon {
padding-right: 12px;
&--warning { /* Used for warning purposes */
color: #D9822B;
}
&--primary { /* Used for general information */
color: #137CBD;
}
&--success { /* Used for verified access */
color: #0F9960;
}
&--danger { /* Used as a hard stop */
color: #DB3737;
}
}
}
I'm genuinely perplexed as to why the padding-right of __icon does not get applied but the color of --warning is
All you are missing is:
.c-banner ..... the dot before the classname
Also, for padding to work they have to be inside --warning because you are chaining to form the full selector and there is no selector that ends with __icon
You can style material-icons if you want to affect multiple:
.c-banner {
.material-icons { padding-right: 12px; }
/* can also do [class*="__icon"] but may be less predictable */
&__icon {
/* rest of the scss */
}
}

Is there a null or undefined or "falsy" value for css custom properties?

I want to create a component and expose certain properties that could be overridden by parent elements.
Here's an example. Let's say I'm creating a button which has its own colors, but allows to change its background color if there's a --button-bg-color defined:
.my-button {
--bg-color: blue;
/* lots of other css... */
/**
* here I assume that there might be a --button-bg-color defined,
* but I have a fallback to my own --bg-color variable
*/
background-color: var(--button-bg-color, var(--bg-color));
}
The problem with the code above is that the --button-bg-color variable is referenced somewhere deep down the styling.
What I wish I could do is the declare somewhere up top that I might want to use this variable. This would tell me that this component expects to be overridden.
Maybe something like this?
.my-button {
--button-bg-color: undefined; /* is there something like undefined? */
--bg-color: blue;
/* the rest of the code is the same */
}
Oh well, I just realized that we can do this:
.my-button {
--bg-color: var(--button-bg-color, blue); /* inherit with fallback */
/* lots of other css... */
background-color: var(--bg-color);
}
This way there's also less repetition.

SMACSS\BEM - how to correctly handle icon style?

I have two nested modules:
<div class="header">
.....
<i class="topIcon"></i>
......
</div>
I have two separate files (I would like to keep it separate because they are reusable parts and can be used separately throughout the application) acting as modules in SMACSS terminology:
Header:
.header {
/* header styles */
}
Icon:
.topIcon {
/* icon styles */
}
Now I want to apply some styles to my topIcon when header has :hover state.
I can put .header:hover .topIcon inside my icon module file and apply style, however from my POV it breaks SMACSS rules.
Do you have any better suggestions?
I use to do it by using Sass' & selector:
.topIcon {
/* icon styles */
.header & {
/* modified styles when it's in header */
}
.header:hover & {
/* modified styles when it's in header thats hovered */
}
}
The result would be
.topIcon {
/* icon styles */
}
.header .topIcon {
/* modified styles when it's in header */
}
.header:hover .topIcon {
/* modified styles when it's in header thats hovered */
}
That way, I keep the icon-related styles in the icon file, but avoid "foreign" classes at a root level.
A weak point of that way might be, that you might also have another rule for .header:hover in the header file, which might be confusing for others, where to place what.

Vendor prefixes in nested Less selector

I am trying to use Less as efficient as possible. Now I want to replace the color of a placeholder, which I normally in CSS would do like this:
input::-webkit-input-placeholder /* WebKit, Blink, Edge */
{
color: #000000;
}
input:-moz-placeholder /* Mozilla Firefox 4 to 18 */
{
color: #000000;
}
input::-moz-placeholder /* Mozilla Firefox 19+ */
{
color: #000000;
}
input:-ms-input-placeholder /* Internet Explorer 10-11 */
{
color: #000000;
}
Now I thought using nested selectors in Less I could use:
input{
&::-webkit-input-placeholder, /* WebKit, Blink, Edge */
&:-moz-placeholder, /* Mozilla Firefox 4 to 18 */
&::-moz-placeholder, /* Mozilla Firefox 19+ */
&:-ms-input-placeholder /* Internet Explorer 10-11 */
{
color: #000000;
}
}
Unfortunately that does not work like I expected. When I only use one selector (without the comma's) it works fine, but that means I would still have to make four nested selectors for each prefix, which is not efficient. How can I accomplish the effect of the first CSS block in Less with the less possible lines?
Note: the full code block is more extensive, with more nested rules. Of course for this example I could just comma all the selectors with just CSS - but I want it to work in a nested Less-selector.
Disclaimer: As always I don't recommend using Less mixins for vendor prefixing stuff. They are best left to libraries like prefix-free or Auto-prefixer. This answer is just to show how similar things can be handled using Less.
Like you've already found out (and mentioned in comments), grouping of vendor prefixed selectors will not work because the User Agent will drop the entire rule when it comes across a selector that it does not understand. You can read more about it in this answer.
This is not a problem with the Less compiler. It will compile and output the code as expected.
One way to avoid writing the four selector blocks again and again would be to put the vendor prefixed selectors into a mixin which accepts a ruleset as argument and then call it wherever required. Below is a sample code for your reference.
.placeholder(#rules){ /* no need to repeat, just copy paste this once in your code */
&::-webkit-input-placeholder /* WebKit, Blink, Edge */
{
#rules();
}
&:-moz-placeholder /* Mozilla Firefox 4 to 18 */
{
#rules();
}
&::-moz-placeholder /* Mozilla Firefox 19+ */
{
#rules();
}
&:-ms-input-placeholder /* Internet Explorer 10-11 */
{
#rules();
}
}
/* call it wherever required */
input{
.placeholder({
color: red;
})
}
input.somethingelse{
.placeholder({
color: black;
padding: 4px;
})
}

#import with Sass not combining files [duplicate]

This question already has answers here:
Import regular CSS file in SCSS file?
(15 answers)
Closed 6 years ago.
I'm new to sass and I'm trying to import a parent theme's css in a Magento application.
I have it working to an extent but not with the result I was expecting.
In my styles.scss folder I have:
#import "../../../rwd/default/css/styles.css";
I have run the sass --watch styles.scss:styles.css in the terminal and the resulting styles.css file has:
#import url(../../../rwd/default/css/styles.css);
In the sass guide it says:
CSS has an import option that lets you split your CSS into smaller,
more maintainable portions. The only drawback is that each time you
use #import in CSS it creates another HTTP request. Sass builds on top
of the current CSS #import but instead of requiring an HTTP request,
Sass will take the file that you want to import and combine it with
the file you're importing into so you can serve a single CSS file to
the web browser.
So I was expecting SASS to import the css as plain old css rules rather than using the #import rule, so my styles.css would look something like:
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/*
* Prevents modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for `hidden` attribute not present in IE 8/9.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/*
* 1. Sets default font family to sans-serif.
* 2. Prevents iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-ms-text-size-adjust: 100%;
/* 2 */
}
/*
* Removes default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/*
* Addresses `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/*
* Addresses `h1` font sizes within `section` and `article` in Firefox 4+,
* Safari 5, and Chrome.
*/
h1 {
font-size: 2em;
}
/*
* Addresses styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/*
* Addresses styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/*
* Corrects font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* Sets consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/*
* Addresses inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/*
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
That way I would have a styles.css on production which didn't use the #import rule.
I got it to work by following this article:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import
#import by default looks for a Sass file to import directly, but if the is a .css file or if the filename is a url it will compile to a CSS #import rule. Both of which were the case for me.
So my solution was to copy the css file I wanted to import & rename it rwd_styles.scss & changed my scss import rule to #import "rwd_styles.scss"; and it worked as I had hoped.

Resources