Making GUI skins with SASS - css

I'm building an HTML5 App that needs to have different skins applied by the user. I'd be keen to hear the best way to go about this with SASS. I'm new to SASS and this solution works but there must be a better way. The method applies and extra class that i'm sure is not needed.
My idea is to compile and ship two css files and then let the user choose over a select tag.
Any advice?
This is some example code that i'm using now:
The "mixin" _skin.scss
$skin: default-skin; // Default skin
//$skin: dark-skin; // Dark skin
.default-skin { // Default Skin
#import 'skins/_default-skin';
}
.dark-skin { // Dark Skin
#import 'skins/dark-skin';
}
// Applying the Skins
html {
#if $skin == default-skin {
#extend .default-skin;
} #else if $skin == dark-skin {
#extend .dark-skin;
} #else {
#extend .default-skin;
}
}
The default skin partial
.nav{
background: $gray-light;
button{
color: $white;
&:active{
color: $gray-lighter;
}
}
}
And the dark skin partial
.nav{
background: $gray-darker;
button{
color: $black;
&:active{
color: $gray-dark;
}
}
}

Related

Angular Material Switch A Color When Switching Theme

I have implemented Angular Material Dark and Light theme. With this I can change the colors based on the theme using for example mat-color($primary). This works fine but now I need to use a different color altogether. So instead of the primary color with hue 200 in light theme: mat-color($primary, 200), I want to be able to use primary color with an 800 hue in dark theme mat-color($primary, 800).
data-table-theme.scss
#mixin data-table-color($color-config) {
$primary: map-get($color-config, primary);
.data-table {
background-color: mat-color($primary, 200);
}
}
data-table.html
<div class="page-container mat-app-background"
[ngClass]="(isDarkTheme$ | async) ? 'theme-dark' : 'theme-default'">
<div class="data-table"></div>
</div>
I tried adding theme-dark selector in custom component style but that didn't work.
#mixin data-table-color($color-config) {
$primary: map-get($color-config, primary);
.theme-default .data-table {
background-color: mat-color($primary, 200);
}
.theme-dark .data-table {
background-color: mat-color($primary, 800);
}
}
I look forward to hearing your solutions.
Edit
The solution I tried doesn't work because angular material generates the css at compile time. So it will then create:
.theme-default .data-table {
background-color: #c5cae9;
}
.theme-dark .data-table {
background-color: #1a237e;
}
.theme-dark .theme-dark .data-table {
background-color: #ff6f00;
}
.theme-dark .theme-default .data-table {
background-color: #ffecb3;
}
This causes it to change hue but the color used is the light primary color.
I have uploaded a test project to Stackblitz, which unfortunately doesn't compile some of the angular material dependencies. But if you run it locally you will see what I mean.
https://stackblitz.com/github/kdrpt/angular-test-project
Have you added the include statement for you mixin in your scss file?
#include data-table-color($color-config);
Just add the above statement in your scss file (where you have defined your #mixin data-table-color) and pass the $color-config that you have created. It is working fine for me.
Looking in your stackblitz example, it seems you forgot to import your app.theme.scss in the root styles.scss.
#import 'theme/app-theme.scss';

Extending in a media query in Sass and Bootstrap 4

I am updating to the new Bootstrap version 4 which now uses Sass over Less, and my application that uses Bootstrap used the Less files directly rather than the fully compiled css distribution.
But now I've hit a snag - I understand that Sass doesn't allow you to use an #extend within a #media query, but what I don't understand is how I get around the simple problem of overloading a style on a larger screen.
For example, a stripped down version of my Sass looks like:
.box {
//mobile styles
background: green;
.logout-button {
//mobile styles for logout button
background: red;
}
}
//everything over 767px
#media (min-width: 768px) {
.box {
.logout-button {
#extend .btn-link; //bring in the Bootstrap button link style here
}
}
}
In this example, I want the .logout-button to use the .btn-link style from Bootstrap. But because you can't #extend like this, I'm totally confused as to how to achieve this.
Is there a completely different approach required in Sass compared to Less? Less allows you to do this so I'd be surprised if this was a limitation considering Bootstrap's recent switch.
Thanks in advance!
You are right, you can not #extend like this.
But you can #include some #mixin.
There is unfortunately no #mixin to create .btn-link variant by default in Bootstrap 4.
If you wanted some other variant, you could use these #mixins which are part of Bootstrap 4:
#include button-variant($background, $border, $active-background: darken($background, 7.5%), $active-border: darken($border, 10%))
or this
#include button-outline-variant($color, $color-hover: #fff)
(Useful list of Boostrap 4 mixins)
But if you need .btn-link you have to make your own #mixin. Something like this (it's copy/paste style of .btn-link in to new mixin):
//
// Link buttons
//
// Make a button look and behave like a link
#mixin btn-link() {
font-weight: $font-weight-normal;
color: $link-color;
background-color: transparent;
#include hover {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
background-color: transparent;
border-color: transparent;
}
&:focus,
&.focus {
text-decoration: $link-hover-decoration;
border-color: transparent;
box-shadow: none;
}
&:disabled,
&.disabled {
color: $btn-link-disabled-color;
pointer-events: none;
}
// No need for an active state here
}
And then you can use it as you wish:
//everything over 767px
#media (min-width: 768px) {
.box {
.logout-button {
#include btn-link;
}
}
}
Nice article about this: SCSS - Extending Classes Within Media Queries

Set a SASS variable depending

I'm searching a way to use a particular color depending on a class on the body tag.
I have a main scss file like this
// variables.scss
$bg-main: white;
$color-first: red;
$color-second: green;
And in my other files, I use the colors
// content.scss
.content {
.some-selector: {
// some styles
color: $color-second;
}
a:hover {
// some styles
color: $color-second;
}
}
// and same goes for menu.scss etc.
Now I have a dynamic class on the body, that changes depending on the current selected menu. I would like $color-second to be different for each body classes, and I don't know how to do that. The only solution I found was to move all the $color-second from each files into one single file, like this:
.body-1 {
.content a:hover, .content .some-selector {
color: green;
}
}
.body-2 {
.content a:hover, .content .some-selector {
color: blue;
}
}
.body-1 {
.content a:hover, .content .some-selector {
color: black;
}
}
So I don't need to write the color in each files. This works well, but if I need to set this $color-second to some other selector, I need to put that in this big file.
Is this possible to do this an other way?
I already checked these answers, but it didn't helped me much:
SASS set variable depending on CSS class
Creating or referencing variables dynamically in Sass
Merge string and variable to a variable with SASS
There are multiple ways to do this. The most obvious two which come to mind are mixins and loops:
Mixins
Just put everything you want into a single mixin, and then use it for every body class:
#mixin colored-content($color) {
.content a:hover, .content .some-selector {
color: $color;
}
/* Any other rules which use $color here */
}
.body-1 {
#include colored-content(green);
}
.body-2 {
#include colored-content('#FF0000');
}
.body-3 {
#include colored-content(darken(red, 20));
}
You can extend this example with any number of arguments (for example, $textColor and $bgColor), conditions or rules.
With this approach you will not have SCSS code repetitions, and any updates will be introduced easily.
Loop
Another way is to use a simple loop:
$body_themes: (
"body-1": green,
"body-2": #FF0000,
"body-3": darken(red, 2)
);
#each $body_class, $color in $body_themes {
.#{$body_class} {
.content a:hover, .content .some-selector {
color: $color;
}
/* Any other rules which use $color here */
}
}
It is even shorter, but imho it is less readable.
P.S. It is possible to combine mixins and loops, by the way :)

How to create 'smart' nested rule for css using webpack and vue

I don't know how to better name this topic
but idea is the following. I want to show different color for a component depends on a parent class.
for this project I use webpack, vue, vue-loader, sass.
I have a sass file this file contents all settings for pages what color should use for specific page
$colors: ".page-home" blue, ".page-about" green;
#each $i in $colors {
$page: nth($i, 1);
$color: nth($i, 2);
#{$page} .component_1, .component_2, .component_n {
color: $color;
}
}
I have a component is written as vue component
#import "colors";
.compoent_1 {
border:1px solid black
}
A issue is I have a lot of components and it very difficult to support the colors file in consistency. When I want to add a new component or remove an old one I always have to go to this file and edit it is annoying me
So how I see the solution is create a main file.
.page-home:blue;
.page-about: green;
I'd like write components in the following style
.component {
border:1px solid black;
color: $PAGE_COLOR;
}
and this code should generate
.page-home .component_1, .component_2, .component_n {
color: blue;
}
.page-about .component_1, .component_2, .component_n {
color: green;
}
thats all. thanks for any suggestion

Foundation customizing scss classes

I am trying to customize scss of foundation to have a two different classes for topbar. I have limited knowledge of scss therefore changing _settings.scss was very easy first step, which has the problem that it changes global style. I would like to do something like following without messing up global styles.
.my-topbar-first {
$topbar-bg-color: $red;
#extend .top-bar;
}
.my-topbar-second {
$topbar-bg-color: $green;
#extend .top-bar;
}
Whats the elegant way to achieve this?
when you are using $topbar-bg-color: $red; it set the $topbar-bg-color variable to what you have in $red variable.when you are using it again, it messed up the last setting.
so instead,
you have to do like this :
.my-topbar-first {
background-color: $red;
#extend .top-bar;
}
.my-topbar-second {
background-color: $green;
#extend .top-bar;
}
First of all you are duplicating code when extending .top-bar in both class names . A more DRY approach would be like this :
.my-topbar-first,
.my-topbar-second {
#extend .top-bar;
}
.my-topbar-first {
background-color: $red;
}
.my-topbar-second {
background-color: $green;
}
When using #extend or #include they should always be on the first line were you declare your properties , example:
my-topbar-second {
#extend .top-bar;
background-color: $green;
color: $white;
font-size: $top-bar-fontsize;
}
If you have more instances of .top-bar-foo you can actually write a for loop, example :
$class-slug: top-bar;
#for $i from 1 through 2 {
.#{$class-slug}-#{$i} {
background-color: $color-#{$i};
}
}
You get :
.top-bar-1 {
background-color: $color-1;
}
.top-bar-2 {
background-color: $color-2;
}
Hope this helped . If you want to learn more about Scss go on Hugo Giraudel's blog http://hugogiraudel.com/ and learn from the best .

Resources