SCSS override variable in nested class [duplicate] - css

I'd like to know if it's possible to define a variable in Sass depending on if a class is set or not. I need to do some font type tests and would like to change the font-variable $basicFont dynamically based on the body class.
E.g.:
$basicFont: Arial, Helvetica, sans-serif;
body {
&.verdana {
$basicFont: Verdana, sans-serif;
}
&.tahoma {
$basicFont: Tahoma, sans-serif;
}
}
Is there a possibility to handle this in Sass?

No. What you're asking for would require Sass to have knowledge of the DOM. Sass only compiles directly to CSS, it is never sent to the browser.
With your sample code, all you're doing is overwriting $basicFont every time. In version 3.4 or later, your variable will only exist within the scope of the block where it was set.
So, your only real options are to make use of mixins or extends.
Extend
This is effective, but is only suitable for very simple cases.
%font-family {
&.one {
font-family: Verdana, sans-serif;
}
&.two {
font-family: Tahoma, sans-serif;
}
}
.foo {
#extend %font-family;
}
Output:
.one.foo {
font-family: Verdana, sans-serif;
}
.two.foo {
font-family: Tahoma, sans-serif;
}
Mixin
This is the method I would recommend if you want a little more fine grained control over which variables are used where.
$global-themes:
( '.one': ('font-family': (Verdana, sans-serif), 'color': red)
, '.two': ('font-family': (Tahoma, sans-serif), 'color': blue)
);
$current-theme: null; // don't touch, this is only used by the themer mixin
#mixin themer($themes: $global-themes) {
#each $selector, $theme in $themes {
$current-theme: $theme !global;
&#{$selector} {
#content;
}
}
}
#function theme-value($property, $theme: $current-theme) {
#return map-get($theme, $property);
}
.foo {
#include themer {
font-family: theme-value('font-family');
a {
color: theme-value('color');
}
}
}
Output:
.foo.one {
font-family: Verdana, sans-serif;
}
.foo.one a {
color: red;
}
.foo.two {
font-family: Tahoma, sans-serif;
}
.foo.two a {
color: blue;
}

Related

Is there any way to make class names the same as the CSS custom variable?

I'm looking for any solution that can reduce this CSS redundancy:
--root {
--brown: #775E3E;
--headline: "Big Shoulders Display", "Oswald", "Open Sans", sans-serif;
}
.brown {color: var(--brown);}
.brown-bg {background-color: var(--brown);}
.headline {font-family: var(--headline);}
The end goal is using .headline and .brown classes directly in HTML.
<h1 class="headline brown">I AM BROWN WITH CUSTOM FONT</h1>
Can this be achieved without having to make an exhausting :root list of colors and then needing to specify each class name (which would be the same) individually?
Basically I want --headline = .headline & --brown = .brown
If there is no simple solution in CSS I am open to using SCSS, a SASS mixin or even javascript.
Thank you all in advance!
You can use SCSS for this. I built a snippet for you. It's self descriptive.
// Arrange them in
// varName: (type, value)
$vars: (
brown: (color, brown),
headline: (font-family, '"Big Shoulders Display", "Oswald", "Open Sans", sans-serif')
);
// Turn all those variables to CSS Variables
:root {
#each $var, $val in $vars {
--#{$var}: #{nth($val, 2)};
}
}
// Create classes out of those variables
#each $var, $val in $vars {
.#{$var} {
#{nth($val, 1)}: var(--#{$var});
}
// If type is color then generate a bg color class
#if nth($val, 1) == color {
.#{$var}-bg {
background-color: var(--#{$var});
}
}
}
Then it will generate CSS like this
:root {
--brown: brown;
--headline: "Big Shoulders Display", "Oswald", "Open Sans", sans-serif;
}
.brown {
color: var(--brown);
}
.brown-bg {
background-color: var(--brown);
}
.headline {
font-family: var(--headline);
}
This is probably what you're looking for. Happy helping.

Declare variable for different classes

I'm using SCSS and I have a variable $arial: 'Arial', serif;
Now I want to do something like that:
.english{
$arial: 'Arial', serif;
font-family: $arial;
}
.japan{
$arial: 'Noto Sans';
font-family: $arial;
}
Because from the beginning, my customer wants to display $arial as 'Arial', but now they're separating it to 2 pages, (English page and Japanese page).
You could use a newer CSS feature called CSS variables to accomplish this. Simple define what variables need to change in what context, and then import them in the definitions themselves. You can find the docs here: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
Here is an example (using very easily distinguishable fonts):
document.querySelector( 'h1' ).addEventListener( 'click', e => document.body.classList.toggle( 'japanese' ) )
body {
--font: 'Comic Sans MS', monospace;
font-family: var(--font, cursive);
}
body.japanese {
--font: 'Impact';
}
<h1>Lorem Ipsum Dolor Sit Amet</h1>
With a simple class toggle, the variable is updated and the definition only needs to be made once.
I suggest you to make use of CSS Vars as above. To accomplish this in sassy way you can make use of sass map
$map:("english":"'Arial',serif","japan":"'Nato Sans'");
#each $key , $value in $map{
.#{$key}{
font-family:unquote($value);
}
}
output
.english {
font-family: 'Arial',serif;
}
.japan {
font-family: 'Nato Sans';
}

Styling `::slotted()` elements from the static styles property

I'm trying to style the :slotted elements in a component from the static styles property as recommended in the docs.
static get styles() {
return [
css `
::slotted(*) {
color: var(--white, #fff);
font-family: "Open Sans", sans-serif;
}
`,
// more styles...
]
}
But for some reason, is getting no effect.
Instead if define the same style in a style element into the render() function it works as expected
<style>
::slotted(*) {
color: var(--white, #fff);
font-family: "Open Sans", sans-serif;
}
// more styles...
</style>
I'm not sure if this is expected (and why) or if this is a bug.
Seems to be a syntax problem in my example. I was using an style array.
This is working fine
static get styles(): CSSResultArray {
return [
css`
:host {
/* styles */
}
::slotted(span) {
/* styles */
}
`,
css`
:host([data-type="primary"]) button {
/* styles */
}
`
];
}

How to change a class format based on body's class with SCSS?

I am making a web app that is used in three (or more) different contexts, and I want each context to have a different color scheme. However, I don't want to have to maintain three different stylesheets when all that changes is colors, typically.
For instance, suppose the themes are red, blue, and orange. One of my stylesheets describes the link colors:
a {
color: $some_color;
}
I want to split this based on the class applied to the body:
body.style1 {
a {
color: $red;
}
}
body.style2 {
a {
color: $blue;
}
}
body.style3 {
a {
color: $orange;
}
}
You can see how this gets unwieldy pretty quickly if you're changing the style for lots of elements. Is there a way to do this more like this?
a {
&closest:body.style1 {
color: $red
}
&closest:body.style2 {
color: $blue;
}
&closest:body.style3 {
color: $orange;
}
}
This way I can code my scss in a clearer, more maintainable way.
It appers you don't have to have the & first, so this works (at least in 3.2.10):
a {
body.style1 & {
color: $red
}
body.style2 & {
color: $blue;
}
body.style3 &{
color: $orange;
}
}
This is what I prefer. Define a mixin like body-style :
#mixin body-style($style, $map) {
body.#{$style} & {
#each $property, $value in $map {
#{$property}: $value;
}
}
}
Then use this for every tag by passing $style as style class of body and $map as map of css keys and values.
a {
#include body-style(style1, (
color: red,
background: white
)
);
}
It will return :
body.style1 a {
color: red;
background: white;
}

Flex 4.5 embedding font not working for tabbars and list items

I am trying to embed a custom font to all elements of my mobile app.
Only the Action Bar and Buttons are changed meanwhile the Tabbars and ListItems doesn't change.
Here's my style.css code
/* CSS file */
#namespace s "library://ns.adobe.com/flex/spark";
/* StyleableTextField, regular */
#font-face {
src: url("assets/fonts/Roboto-Light.ttf");
fontFamily: "robotoLight";
fontWeight: bold;
embedAsCFF: false;
}
/* Label, regular */
#font-face {
src: url("assets/fonts/Roboto-Light.ttf");
fontFamily: "robotoLightCFF";
fontWeight: normal;
embedAsCFF: true;
}
s|Label {fontFamily: "robotoLightCFF";}
s|ActionBar {fontFamily: "robotoLight";}
s|LabelItemRenderer {fontFamily: "robotoLight";}
s|Button {fontFamily: "robotoLight";}
s|TabbedViewNavigator #tabBar {fontFamily: "robotoLight";}
s|TextInput {fontFamily: "robotoLight";}
s|View {fontFamily: "robotoLight";}
global
{
text-align: left;
content-background-color: #FFFFFF;
content-background-alpha: 0.59;
fontFamily: "robotoLight";
}
/** this is the bar the top of the app **/
s|ActionBar{
chromeColor:#4D99E0; /* more like background color */
titleAlign:center;
textShadowAlpha: 0;
}
/* This is the styling of the tabbed navigator */
s|TabbedViewNavigator #tabBar {
chromeColor: #4D99E0; /* color of background on buttons */
color: #ffffff; /* color of text on tab names */
}
.playButton,.pauseButton,.resumeButton,.initButton {
chromeColor: #4D99E0;
color: #fff;
}
And here's a screenshot of how it appears:
screenshot http://samzkingdom.com/wp-content/uploads/2014/01/Capture.png
How do I do this? Or what am I doing wrong?
[EDIT]
It is totally my mistake that I just tested on the emulator on my Desktop. It works perfectly on the Android device.
Try this for tab navigator. Just replace the font family okay..
.tabNavigator
{
font-family: "Helvetica Neue";
font-weight:normal;
horizontal-gap:1;
tab-style-name:"myTabs";
corner-radius:0;
selected-tab-text-style-name: "myselectedTabs";
border-color:#D6D6D6;
}
.myTabs
{
font-size:13;
font-family: "Helvetica Neue";
font-weight:normal;
fill-colors:"#e5e5e5","#f6f6f6";
fill-alphas:1,1;
color:#000000;
corner-radius:0;
text-selected-color:#000000;
text-roll-over-color:#000000;
border-color:#D6D6D6;
}
.myselectedTabs
{
font-size:13;
font-family: "Helvetica Neue";
font-weight:normal;
fill-colors:"#FFFFFF","#FFFFFF";
fill-alphas:1,1;
color:#0d7dbd;
corner-radius:0;
text-selected-color:#0d7dbd;
text-roll-over-color:#0d7dbd;
}
For StyleableTextField (used in many UI elements in mobile Flex, for example in ListItemRenderer) you should use embedAsCFF: false; as explained in Adobe's blog Embedding Fonts in Flex Mobile Projects
For example the following works for me (for the Lists):
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
s|ActionBar {
chromeColor: #0066CC;
color: #FFFFFF;
titleAlign: center;
/* textShadowAlpha: 0; */
textShadowColor: #000000;
}
#font-face {
src: url("/assets/fonts/arial.ttf");
fontFamily: embFont;
embedAsCFF: false; /* required for StyleableTextField */
unicodeRange:
U+0020-U+0040, /* Punctuation, Numbers */
U+2660-U+2666, /* Card suits */
U+0041-U+005A, /* Upper-Case A-Z */
U+0061-U+007A, /* Lower-Case a-z */
U+0410-U+0451; /* Cyrillic */
}
s|LabelItemRenderer {
fontFamily: embFont;
}

Resources