Sass Mixin Themify not Effecting Body - css

I've inherited some SASS code used for theming from someone and it looks like it is only compiling into rules that target children of the element that has the themed class.
$themes:(
default:(
background:#CCCCCC
)
);
#mixin themify($themes: $themes) {
#each $theme, $map in $themes {
.theme-#{$theme} & {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#content;
$theme-map: null !global;
}
}
}
#function themed($key) {
#return map-get($theme-map, $key);
}
Gives a compiled css rule as
.theme-default body {
background-color: #CCCCCC;
}
The code seems fine but the highest element that can have the themed class is the body but then how can the body be given a themed property? I tried to add an additional mixin that will not use the children (just removing the & to invert the element relation)
#mixin themifyDirect($themes: $themes) {
#each $theme, $map in $themes {
.theme-#{$theme} {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#content;
$theme-map: null !global;
}
}
}
But this compiles into a css rule
body .theme-default {
background-color: #26282F; }
This is close but not enough because the rule I need is
body.theme-default {
background-color: #CCCCCC;
}
To target body which has the class

#mixin themifyDirect($themes: $themes) {
#each $theme, $map in $themes {
&.theme-#{$theme} {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#content;
$theme-map: null !global;
}
}
}
outputs
body.theme-default {
background-color: #CCCCCC;
}
You we're really close - note the leading '&' on line 3 which removes the space.

Related

Use Sass #content and unify parent selector to immediate child selector

I'm trying to use Sass / SCSS to unify the #content directive to the parent class. I am attempting to use a conditional statement within the mixin to allow for both use cases:
$themes: (
Light: (
page_background: #ffffff,
),
Dark: (
page_background: #181818,
)
);
#function get_color($key) {
#return map-get($theme-map, $key);
}
#mixin theme($makeAncestor: true) {
#each $theme, $map in $themes {
$theme-map: $map !global;
#if $makeAncestor {
.#{$theme} & {
#content;
}
} #else {
.#{$theme} & {
#content;
}
}
}
$theme-map: null !global;
}
.fixed {
#include theme() {
background: get_color(page_background);
}
}
Here is the output:
.Light .fixed {
background: #ffffff;
}
Desired output:
.Light.fixed {
background: #ffffff;
}
You can use #at-root in your mixin and interpolate the parent selector:
#mixin theme($makeAncestor: true) {
#at-root {
#each $theme, $map in $themes {
$theme-map: $map !global;
#if $makeAncestor {
.#{$theme}#{&} {
#content;
}
} #else {
.#{$theme}#{&} {
#content;
}
}
}
$theme-map: null !global;
}
}

How to give opacity to background-color using Saas variables color themes mixins?

This is my mixins for themes color
$themes: (
light: (
black-color: black,
),
dark: (
black-color: rgb(235, 13, 161),
)
);
#mixin themify($themes) {
#each $theme, $map in $themes {
.theme-#{$theme} & {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#content;
$theme-map: null !global;
}
}
}
#function themed($key) {
#return map-get($theme-map, $key);
}
This is my class where i am appending property with variables
.overlay {
#include themify($themes) {
background-color: themed(black-color, .5);
box-shadow: 1px 1px 1px themed(black-color, .5);
}
}
But opacity not working and following error getting
Sass Error: Only 1 argument allowed, but 2 were passed.
If you don't use the black-color anywhere else you could try redefining them as:
$themes: (
light: (
black-color: rgba(0, 0, 0, 0.5),
),
dark: (
black-color: rgba(235, 13, 161, 0.5),
)
);

Reduce amount of CSS generated by a SASS function

I'm very new to the (I guess) more advanced features of SASS. Referencing this article I've been able to create a SASS setup that lets me easily do dark mode theming! I'd like to reduce the amount of CSS it generates, however, and wanted to know if I've reached the limit of my knowledge or just what SASS/CSS is capable of.
I have this map of "themes":
$themes: (
light: (
primaryOne: #f0f,
primaryTwo: #0ff
),
dark: (
primaryOne: #000,
primaryTwo: #111
)
);
I have these mixins/functions that were mostly lifted from the article:
#mixin themify($themes: $themes) {
#each $theme, $map in $themes {
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#if $theme == dark {
#media (prefers-color-scheme: dark) {
#content;
}
} #else {
#content;
}
$theme-map: null !global;
}
}
#function themed($key) {
#return map-get($theme-map, $key);
}
And finally a custom mixin and the class where I'm using it:
#mixin set-color-primary {
#include themify($themes) {
color: themed('primaryOne');
}
}
.foo-container div {
#include set-color-primary;
}
Finally this generates CSS like the following:
.foo-container div {
color: #f0f;
}
#media (prefers-color-scheme: dark) {
.foo-container div {
color: #000;
}
}
I was hoping I could squeeze out a few more lines and get something more like:
.foo-container div {
color: #f0f;
#media (prefers-color-scheme: dark) {
color: #000;
}
}
Is this a limitation of my SASS knowledge or is this not possible in plain CSS?

How to Change High Contrast Background Images using SASS

I am trying to make a mixin for standard background images and high contrasted background images, not sure how do i do it. can someone pl. shade some light
I have a mixin for text color and background color :
$colors:(
standard: (
primary-color-blue: #2aace2,
mid-blue-color:#2695d2,
dark-blue-color:#124b62
),
contrasted: (
primary-color-blue: #177eab,
mid-blue-color:#1c6f9b,
dark-blue-color:#124b62
)
);
#function get-color($key, $type: 'standard'){
#each $name, $color in map-get($colors, $type){
#if($key == $name){
#return $color
}
}
}
#mixin get-color($property,$color){
#{$property}: get-color($color);
#at-root body.contrasted & {
#{$property}: get-color($color, contrasted);
}
}
.className{
#include get-color(background-color, primary-color-blue)
}
output :
.className {
background-color: #2aace2;
}
body.contrasted .className {
background-color: #177eab;
}
Thanks !!
EDITED AS PER ANSWER : Edited with extra color / transparent variable, but throws error Edited with extra color / transparent variable, but throws error
$images:(
standard: (
pdp-more-icon-mob: white + $img_file_path + 'product-detail-page/Product-surface-display/more-icon/More-Mobile.png',
pdp-more-icon-mob-retina : #f00 + $img_file_path + 'product-detail-page/Product-surface-display/more-icon/More-Mobile__2x.png'
),
contrasted: (
pdp-more-icon-mob: green + $img_file_path + 'product-detail-page/Product-surface-display/more-icon/More-Desktop-High-Contrast.png',
pdp-more-icon-mob-retina : $green + $img_file_path + 'product-detail-page/Product-surface-display/more-icon/More-Desktop-High-Contrast__2x.png'
)
);
#function get-images($key, $type: 'standard'){
#each $name, $image in map-get($images, $type){
#if($key == $name){
#return $image
}
}
}
#mixin get-images($property, $color, $image, $retina:false){
#{$property}: get-images($color + $image);
#at-root body.contrasted & {
#{$property}: get-images($color + $image, contrasted);
}
#if($retina){
#media (-webkit-min-device-pixel-ratio: 2){
#{$property}: get-images($color + $image#{-retina});
#at-root body.contrasted & {
#{$property}: get-images($color + $image#{-retina}, contrasted);
}
}
}
}
.className{
#include get-images(background, color, image, true);
}
Without refactoring the mixin is possible to use it this way—by adding your images properly in your map:
$colors:(
standard: (
primary-color-blue: #2aace2,
mid-blue-color:#2695d2,
dark-blue-color:#124b62,
image: 'img.png',
image-retina: 'img-retina.png'
),
contrasted: (
primary-color-blue: #177eab,
mid-blue-color:#1c6f9b,
dark-blue-color:#124b62,
image: 'img2.png',
image-retina: 'img2-retina.png'
)
);
#function get-color($key, $type: 'standard'){
#each $name, $color in map-get($colors, $type){
#if($key == $name){
#return $color
}
}
}
#mixin get-color($property,$color){
#{$property}: get-color($color);
#at-root body.contrasted & {
#{$property}: get-color($color, contrasted);
}
}
.className{
#include get-color(background-image, image);
#media (-webkit-min-device-pixel-ratio: 2){
#include get-color(background-image, image-retina)
}
}
But you can also adapt this mixin for images and do so:
$images:(
standard: (
image: 'img.png',
image-retina: 'img-retina.png'
),
contrasted: (
image: 'img2.png',
image-retina: 'img2-retina.png'
)
);
#function get-images($key, $type: 'standard'){
#each $name, $image in map-get($images, $type){
#if($key == $name){
#return $image
}
}
}
#mixin get-images($property,$image, $retina:false){
#{$property}: get-images($image);
#at-root body.contrasted & {
#{$property}: get-images($image, contrasted);
}
#if($retina){
#media (-webkit-min-device-pixel-ratio: 2){
#{$property}: get-images($image#{-retina});
#at-root body.contrasted & {
#{$property}: get-images($image#{-retina}, contrasted);
}
}
}
}
.className{
#include get-images(background-image, image, true);
}
Where the true in 'get-images' is calling to image + '-retina' in the $images map, and outputs:
.className {
background-image: "img.png";
}
body.contrasted .className {
background-image: "img2.png";
}
#media (-webkit-min-device-pixel-ratio: 2) {
.className {
background-image: "img-retina.png";
}
body.contrasted .className {
background-image: "img2-retina.png";
}
}

Sass ampersand and two parents together in mixin?

I'm faced with the task of theming the site. I found a suitable mixin. Everything would work well, if not for the mixin for events. It turns out that I need to do something, so that if the topic's mixin is invoked in the mixin of events, then the class did not go cascade, but substituted for the topic class, the .no-touchevents class on the html tag.
Ideally, that would be so on the output:
.card {
color: #fff;
}
.t-dark .card {
color: #000;
}
.no-touchevents .card:hover {
color: #000;
}
.t-dark.no-touchevents .card:hover {
color: #fff;
}
It's a little hacky (or maybe a lot hacky) but by adding an additional parameter to the themify mixin and building our selector manually, you can achieve the output you're looking for.
$themes: (
dark: (
colorDark: #000,
colorLight: #fff
)
);
#mixin on-event() {
.no-touchevents &:hover {
#content;
}
}
#mixin themify($themes, $flat: ' ') { // Add a parameter to separate by default
#each $theme, $map in $themes {
#at-root .t-#{$theme}#{$flat}#{&} { // Build our selector manually
$theme-map: () !global;
#each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
#content;
$theme-map: null !global;
}
}
}
#function themed($key) {
#return map-get($theme-map, $key);
}
.card {
color: #fff;
#include themify($themes) {
color: themed('colorDark')
}
#include on-event() {
color: #000;
#include themify($themes, '') { // Tell themify not to separate selectors
color: themed('colorLight')
}
}
}

Resources