How to Change High Contrast Background Images using SASS - css

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";
}
}

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;
}
}

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?

Scss array branding stylesheet

I wanted to use a Scss solution to easily modify styles on a website with multiple branded sub sites. My aim was to get arrays for elements (classes, ids, tags) which share styling properties and just have those arrays to be edited when adjusting brand styles.
I came up with the following solution which works fine, however... Couldn't the following be done in a smarter way? i.e. less chunks of "$array... + $all.. + #each"? Hope you know what I mean when you see my current syntax:
// All elements with background colors
$arrayElementsWithBackgroundColor: (
'.example-1',
'.example-2' // etc.
);
$allElementsWithBackgroundColor: ();
#each $item in $arrayElementsWithBackgroundColor {
$allElementsWithBackgroundColor: append($allElementsWithBackgroundColor, unquote('#{$item}'), 'comma');
};
// All elements with background gradients
$arrayElementsWithBackgroundColorGradient: (
'.example-3',
'.example-4' // etc.
);
$allElementsWithBackgroundColorGradient: ();
#each $item in $arrayElementsWithBackgroundColorGradient {
$allElementsWithBackgroundColorGradient: append($allElementsWithBackgroundColorGradient, unquote('#{$item}'), 'comma');
};
// All elements with semi-transparent background colors
$arrayElementsWithBackgroundColorSemiTransparent: (
'.example-5',
'.example-6' // etc.
);
$allElementsWithBackgroundColorSemiTransparent: ();
#each $item in $arrayElementsWithBackgroundColorSemiTransparent {
$allElementsWithBackgroundColorSemiTransparent: append($allElementsWithBackgroundColorSemiTransparent, unquote('#{$item}'), 'comma');
};
// All elements with border colors
$arrayElementsWithBorderColor: (
'.example-7',
'.example-8' // etc.
);
$allElementsWithBorderColor: ();
#each $item in $arrayElementsWithBorderColor {
$allElementsWithBorderColor: append($allElementsWithBorderColor, unquote('#{$item}'), 'comma');
};
// All elements with text colors
$arrayElementsWithTextColor: (
'.example-9',
'.example-10' // etc.
);
$allElementsWithTextColor: ();
#each $item in $arrayElementsWithTextColor {
$allElementsWithTextColor: append($allElementsWithTextColor, unquote('#{$item}'), 'comma');
};
Those chunks are where I collect my arrays of elements to be branded. Afterwards I'm using those like this:
body {
#at-root #{&}.brand-1 {
#{$allElementsWithBackgroundColor} { background: $brand-1; }
#{$allElementsWithBackgroundColorGradient} { background: $brand-1-gradient; }
#{$allElementsWithBackgroundColorSemiTransparent} { background: rgba($brand-1,0.8); }
#{$allElementsWithBorderColor} { border-color: $brand-1; }
#{$allElementsWithTextColor} { color: $brand-1; }
}
#at-root #{&}.brand-2 {
#{$allElementsWithBackgroundColor} { background: $$brand-2; }
#{$allElementsWithBackgroundColorGradient} { background: $$brand-2-gradient; }
#{$allElementsWithBackgroundColorSemiTransparent} { background: rgba($$brand-2,0.8); }
#{$allElementsWithBorderColor} { border-color: $$brand-2; }
#{$allElementsWithTextColor} { color: $$brand-2; }
}
#at-root #{&}.brand-3 {
#{$allElementsWithBackgroundColor} { background: $brand-3; }
#{$allElementsWithBackgroundColorGradient} { background: $brand-3-gradient; }
#{$allElementsWithBackgroundColorSemiTransparent} { background: rgba($brand-3,0.8); }
#{$allElementsWithBorderColor} { border-color: $brand-3; }
#{$allElementsWithTextColor} { color: $brand-3; }
}
#at-root #{&}.brand-4 {
#{$allElementsWithBackgroundColor} { background: $brand-4; }
#{$allElementsWithBackgroundColorGradient} { background: $brand-4-gradient; }
#{$allElementsWithBackgroundColorSemiTransparent} { background: rgba($brand-4-alt,0.8); }
#{$allElementsWithBorderColor} { border-color: $brand-4; }
#{$allElementsWithTextColor} { color: $brand-4; }
}
}
You could consider using maps – like:
// _brands.scss
$brand-1: red;
$brand-2: green;
$brand-3: orange;
$brand-4: blue;
$brand-1-gradient: linear-gradient(to top, red, red);
$brand-2-gradient: linear-gradient(to top, green, green);
$brand-3-gradient: linear-gradient(to top, orange, orange);
$brand-4-gradient: linear-gradient(to top, blue, blue);
$brands: (
brand-1 : (
// note! you can add more properties to each style map
'.example-1, .example-2': (background: $brand-1, color: magenta ),
'.example-3, .example-4': (background: $brand-1-gradient ),
'.example-5, .example-6': (background: rgba($brand-1, 0.8) ),
'.example-7, .example-8': (border-color: $brand-1 ),
'.example-9, .example-10': (color: $brand-1 )
),
brand-2 : (
'.example-1, .example-2': (background: $brand-2 ),
'.example-3, .example-4': (background: $brand-2-gradient ),
'.example-5, .example-6': (background: rgba($brand-2, 0.8) ),
'.example-7, .example-8': (border-color: $brand-2 ),
'.example-9, .example-10': (color: $brand-2 )
),
brand-3 : (
'.example-1, .example-2': (background: $brand-3 ),
'.example-3, .example-4': (background: $brand-4-gradient ),
'.example-5, .example-6': (background: rgba($brand-3, 0.8) ),
'.example-7, .example-8': (border-color: $brand-3 ),
'.example-9, .example-10': (color: $brand-3 )
),
brand-4 : (
'.example-1, .example-2': (background: $brand-4 ),
'.example-3, .example-4': (background: $brand-4-gradient ),
'.example-5, .example-6': (background: rgba($brand-4, 0.8) ),
'.example-7, .example-8': (border-color: $brand-4 ),
'.example-9, .example-10': (color: $brand-4 )
)
);
// brands.scss
#import '_brands.scss'
body {
#each $brand, $selectors in $brands {
#at-root #{&}.#{$brand} {
#each $selector, $style in $selectors {
#{$selector}{
#each $property, $value in $style {
#{$property}: $value;
}
}
}
}
}
}
You could also chose to split each brand into individual stylesheets using a mixin
// add to _brand.scss
#mixin brand($brand-name) {
body {
#at-root #{&}.#{$brand-name} {
#each $selector, $style in map-get($brands, $brand-name) {
#{$selector}{
#each $property, $value in $style {
#{$property}: $value;
}
}
}
}
}
}
// brand1.scss
#import '_brands.scss';
#include brand(brand-1);
// brand2.scss
#import '_brands.scss';
#include brand(brand-2);
// brand3.scss
#import '_brands.scss';
#include brand(brand-3);
// brand4.scss
#import '_brands.scss';
#include brand(brand-4);

Strange character appending to SCSS #mixin

In the following scenario I need to support as many browsers as possible.
I am building a SCSS #mixin that prefixes background-image with vendor prefixes, but also listens to see if a linear-gradient is declared, and if it is, then prefix that as well.
My code looks like this:
#function str-coerce($string) {
#return inspect($string);
}
#function str-replace($string, $find, $replace: "") {
$index: str-index($string, $find);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($find)), $find, $replace);
}
#return $string;
}
#mixin background-image($values...) {
$vendors: (-webkit-, -moz-, -o-);
#each $vendor in $vendors {
$string: str-coerce($values);
#if (str-index($string, "linear-gradient")) {
$string: str-replace($string, "linear-gradient", #{$vendor + "linear-gradient"});
#if (str-index($vendor, "-o-")) {
$vendor: str-replace($vendor, "-o-");
}
#{$vendor + "background-image"}: $string;
} #else {
#if not (str-index($vendor, "-o-")) {
#{$vendor + "background-image"}: $values;
}
}
}
background-image: $values;
}
Usage and output looks like this:
// usage
.foo {
#include background-image(url("../example.svg"));
}
.bar {
#include background-image(linear-gradient(45deg, red, blue));
}
// output
.foo {
-webkit-background-image: url("../example.svg");
-moz-background-image: url("../example.svg");
background-image: url("../example.svg");
}
.bar {
-webkit-background-image: (-webkit-linear-gradient(45deg, red, blue),);
-moz-background-image: (-moz-linear-gradient(45deg, red, blue),);
background-image: (-o-linear-gradient(45deg, red, blue),);
background-image: linear-gradient(45deg, red, blue);
}
My question is, what is going wrong in my type coercion that is causing my linear-gradient vendor prefixes to be wrapped in brackets and followed with a comma? e.g. (-moz-linear-gradient(45deg, red, blue),).
While I'm not entirely sure why your values are being wrapped in (), you can use the str-replace function to remove them.
To remove the leading ( update your str-replace function to:
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 2) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
#return $string;
}
Then update this line to remove the trailing ),
#{$vendor + "background-image"}: str-slice($string, 1, -3);

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