#mixin scss with nested elements is possible? - css

I'm trying to use a mixin to make the code less repetitive, but I can't reach the nested elements.
Could anyone tell me if this approach is possible?
#mixin schema-calendar($backgroundColor: var(--ion-color-primary), $titleColor: var(--ion-color-secondary)) {
background-color: $backgroundColor !important;
.switch-btn,
ion-icon {
color: $titleColor !important;
text-transform: uppercase;
}
.week-toolbar li {
color: $titleColor !important;
font-weight: 900;
}
button.today p { color: $titleColor !important; }
button.on-selected {
p { color: var(--ion-color-secondary-contrast) !important;}
}
}
ion-calendar.schemaDefault {
#include schema-calendar();
}
ion-calendar.schemaBlackRed {
#include schema-calendar(var(--ion-card-black-red));
}
ion-calendar.schemaIndigo {
#include schema-calendar(var(--ion-card-indigo), var(--ion-color-light));
}
When used directly in css it works perfectly, I know that when scss is compiled to css the code is modified but the result is the same, but when I use the mixin according to the code above, only the background-color property is applied.
ion-calendar.schemaBlackRed {
// primaryColor: 'var(--ion-card-blackred)', secondaryColor: 'var(--ion-color-secondary)', titleColor: 'var(--ion-color-secondary)',
background-color: var(--ion-card-black-red) !important;
.switch-btn,
ion-icon {
color: var(--ion-color-secondary) !important;
text-transform: uppercase;
}
.week-toolbar li {
color: var(--ion-color-secondary) !important;
font-weight: 900;
}
button.today p { color: var(--ion-color-secondary) !important; }
button.on-selected {
p { color: var(--ion-color-secondary-contrast) !important;}
}
}

I found that the problem was occurring because I had included the style at the page level, moved the code from the initial Ionic load and everything worked as expected.

Related

How to import a scss file inside a scss class

I want to add a different theme when i add "dark-theme" class to body. My implementation looks like this:
#import '../../../../node_modules/angular-grids/styles/material.scss';
.app-dark {
#import '../../../../node_modules/angular-grids/styles/material-dark.scss';
}
Without any luck. Any clue on how to do this?
There are two methods in order to do that. Both of them include mixins.
meta.load-css
The sass:meta feature gives the ability to do what you want.
Say you have this scss file with a theme:
//theme/_code.scss
$border-contrast: false !default;
code {
background-color: #6b717f;
color: #d2e1dd;
#if $border-contrast {
border-color: #dadbdf;
}
}
you can include that code inside another scss file like so:
// other-theme.scss
#use "sass:meta";
body.dark {
#include meta.load-css("theme/code",
$with: ("border-contrast": true));
}
This will result in the following css:
body.dark code {
background-color: #6b717f;
color: #d2e1dd;
border-color: #dadbdf;
}
You can read more about this feature here
old fashioned mixin
But you can do basically the same thing if you use mixin and include.
So, let's say you have this class you want to import into another class:
.title {
font-size: 2em;
font-weight: bold;
}
And another sass file with another theme:
.dark-theme {
.title {
font-size: 2em;
font-weight: bold;
color: white;
}
}
You can use a scss mixin and import it into both files:
mixin.scss
#mixin shared-items() {
.title {
font-size: 2em;
font-weight: bold;
}
}
then, in the theme files:
white-theme.scss
#import './mixin.scss';
/* will be included as is without a parent class */
#include shared-items;
dark-theme.scss
#import './mixin.scss';
/* will be included inside the dark-theme class */
.dark-theme {
.title {
color: white;
}
#include shared-items;
}
this will generate this css:
.title {
font-size: 2em;
font-weight: bold;
}
.dark-theme {
.title { color: white; }
.title {
font-size: 2em;
font-weight: bold;
}
}
Notice that you can also pass parameters to mixin and use them as functions.
So you can easily pass colors and use them with your theme variables.
for example:
# an example of giving a color to a placeholder mixin:
#mixin nk-placeholder($color: #C4C4CC) {
&::-webkit-input-placeholder {
color: $color;
font: inherit;
}
&::-moz-placeholder {
color: $color;
font: inherit;
}
&:-ms-input-placeholder {
color: $color;
font: inherit;
}
&:-moz-placeholder {
color: $color;
font: inherit;
}
&::placeholder {
color: $color;
font: inherit;
}
}
# same thing as above
#mixin shared-items($text-color: black) {
.title {
font-size: 2em;
font-weight: bold;
color: $text-color;
}
}
.white-theme {
#include shared-items;
}
.dark-theme {
#include shared-items(white);
}

Sass with BEM, inherit selector

I'm using Sass 3.4.1 and BEM so my scss is:
.photo-of-the-day{
&--title{
font-size: 16px;
}
}
and I want every time hover over .photo-of-the-day something happen with title, that's pretty common so usually in css:
.photo-of-the-day:hover .photo-of-the-day--title{
font-size:12px
}
the thing is using BEM this is the only way I found and looks kinda ugly
.photo-of-the-day{
&--title{
font-size: 16px;
}
&:hover{
background: red;
/* this is ugly */
.photo-of-the-day--title{
text-decoration: underline;
}
}
}
so I was wondering if I can inherit .photo-of-the-day selector and use it inside the hover to avoid copy again the full selector.
Ideally would be something like:
.photo-of-the-day{
&--title{
font-size: 16px;
}
&:hover{
background: red;
&&--title{
text-decoration: underline;
}
}
}
Or something close to comeback to the parent selector for BEM. Is it possible?
If you insist on nesting everything, the best you can do is this:
.photo-of-the-day {
$root: &;
&--title{
font-size: 16px;
}
&:hover{
#{$root}--title {
text-decoration: underline;
}
}
}
You can use this syntax:
.photo-of-the-day {
&--title {
font-size: 16px;
}
&:hover &--title {
text-decoration: underline;
}
}

CSS comments in nested LESS rules

How can I add CSS comments in LESS nested rules? Ex:
div{
span{
font-size: 16px;
color: #fff;
}
/*This is my comment*/
em{
color: blue;
}
}
This is the output I expect to get:
div span {
font-size: 16px;
color: #fff;
}
/*This is my comment*/
div em {
color: blue;
}
But, unfortunatelly this is how it is processed:
div {
/*This is my comment*/
}
div span {
font-size: 16px;
color: #fff;
}
div em {
color: blue;
}
Is it possible to make this?
This isn't possible using /* */.
The reason being that it is still under the div scope, so it won't work using /* */ comments.
However, in LESS you can use // for single line comments which doesn't go through the compiler (so doesn't end up in the compiled CSS code but will be in the LESS code).
Here is the official documentation on comments.
Well, you can get your comment inside nested rules:
div {
em {
/* This is my comment */
color: blue;
}
}
output:
div em {
/* This is my comment */
color: blue;
}
I hope this would be useful for you.
/*This is my comment*/
div {
em {
color: blue;
}
span {
font-size: 16px;
color: #fff;
}
}
and the output will be,
/*This is my comment*/
div em {
color: blue;
}
div span {
font-size: 16px;
color: #fff;
}
More or less it would be like what you are expecting !!!

SASS: content block mixin (or placeholder) that takes contextual selectors and appends them to selector in mixin

I want to do something like this:
#mixin context($size) {
body.#{$size} {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
& {
font-size: 5em;
}
}
}
}
To produce:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
What it ACTUALLY (predictably) produces:
div span {
font-size: 2em;
}
div span body.large {
font-size: 5em;
}
I could just replicate the selectors inside different mixins, but given that selectors could be complex that's a lot of extra junk:
#include context('large') {
div {
span {
font-size: 5em;
}
}
}
I could make the selectors into mixins so I don't have to repeat them each time, but...
Isn't there a way to use placeholders, maybe in combination with mixins, to get what I want in the first two code blocks above?
You just need to move the & to be part of the mixin:
#mixin context($size) {
body.#{$size} & {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
Output:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
As of Sass 3.4, you can write this to work both inside a selector and at the root of the document:
#mixin optional-at-root-nest($sel) {
#at-root #{if(not &, $sel, selector-nest($sel, &))} {
#content;
}
}
#mixin context($size) {
#include optional-at-root-nest('body.#{$size}') {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
#include context('large') {
font-size: 2em;
}

Nested mixins or functions in SASS

Some body know how can i use nested mixins or functions in SASS?
I have something like this:
#mixin A(){
do something....
}
#mixin B($argu){
#include A();
}
yeah you already doing it right. You can call first mixin in second one. check this pen http://codepen.io/crazyrohila/pen/mvqHo
You can multi nest mixins, you can also use place holders inside mixins..
#mixin a {
color: red;
}
#mixin b {
#include a();
padding: white;
font-size: 10px;
}
#mixin c{
#include b;
padding:5;
}
div {
#include c();
}
which gives out CSS
div {
color: red;
padding: white;
font-size: 10px;
padding: 5;
}
As mentioned in the other answers, you can include mixins in other mixins. In addition, you can scope your mixins.
Example
.menu {
user-select: none;
.theme-dark & {
color: #fff;
background-color: #333;
// Scoped mixin
// Can only be seen in current block and descendants,
// i.e., referencing it from outside current block
// will result in an error.
#mixin __item() {
height: 48px;
}
&__item {
#include __item();
&_type_inverted {
#include __item();
color: #333;
background-color: #fff;
}
}
}
}
Will output:
.menu {
user-select: none;
}
.theme-dark .menu {
color: #fff;
background-color: #333;
}
.theme-dark .menu__item {
height: 48px;
}
.theme-dark .menu__item_type_inverted {
height: 48px;
color: #333;
background-color: #fff;
}
Scoping mixins means that you can have multiple mixins named the same in different scopes without conflicts arising.

Resources