I'm creating multiple themes with scss in ionic. I ended up with 2 ways, but which one is better and why?
First way
$colors: (
primary: #bdc3c7,
secondary: #444444,
danger: #7f8c8d,
light: #34495e,
dark: #e74c3c
);
.light-theme {
// main style for all the commi themes app
ion-content {
background-color: color($colors, light);
}
#import "main";
}// light-theme
second way
.light-theme {
$colors: (
primary: #bdc3c7,
secondary: #444444,
danger: #7f8c8d,
light: #34495e,
dark: #e74c3c
);
// main style for all the commi themes app
ion-content {
background-color: color($colors, light);
}
#import "main";
}//
The first way I have the colors outside the class and the second way the colors are inside the class and the both ways are working. I'm thinking about what would happen if we have at least three themes?
Just fantasy. Sassmeister demo.
Let's define an array of themes:
$themes: (
default: ( // theme name
// some colors. colors names are the same for all themes
primary: red,
secondary: blue
),
dark: (
primary: red-dark,
secondary: blue-dark
),
light: (
primary: red-light,
secondary: blue-light
)
);
Then set the $theme variable. It refers to one of the elements of $themes array. We will always get color values form this variable.
$theme: map-get($themes, default);
Boring mixin to get color value by name. $theme used here.
#function color($color-name) {
#return map-get($theme, $color-name);
}
Mixin stylish that redefines the value of $theme variable. We use !global flag to make this variable accessible from any scope. This mixin generates class name .theme-name before our selector for all themes but not default.
#mixin stylish($theme-name: 'default') {
$theme: map-get($themes, $theme-name) !global;
#if ($theme-name == 'default') {
#content;
} #else {
.theme-#{$theme-name} & {
#content;
}
}
}
And now we can write code like this:
.block {
#include stylish() {
color: color(primary);
}
&__element {
#include stylish() {
color: color(primary);
}
#include stylish(dark) {
color: color(primary);
}
#include stylish(light) {
color: color(primary);
}
}
}
Css output:
.block {
color: red;
}
.block__element {
color: red;
}
.theme-dark .block__element {
color: red-dark;
}
.theme-light .block__element {
color: red-light;
}
This mixin can generate all themes. Demo.
#mixin global-stylish() {
#include stylish() {
#content;
}
#include stylish(dark) {
#content;
}
#include stylish(light) {
#content;
}
}
Usage:
&__element {
#include global-stylish() {
color: color(secondary);
}
}
Thank you for opening sass way , here is my end code
$themes:(
theme:(
primary: #032838,
secondary: #868a6f,
danger: #ed4039,
light: #f3f2f2,
dark: #37aad9
),
light:(
primary: #34495e,
secondary: #e74c3c,
danger: #7f8c8d,
light: #bdc3c7,
dark: #444444
),
dark:(
primary: #f3f2f2,
secondary: #3D8EB9,
danger: #e74c3c,
light: #303030,
dark: #212121
),
main:(
black: #000000,
white: #ffffff,
wisteria: #8e44ad,
pomegranate:#c0392b,
orange: #f39c12,
green: #03A678,
)
);
$color-key: primary !default;
#function color(
$theme-name: commi,
$color-key: $color-key,
$opacity: 1
){
$color: null;
$theme: map-get($themes, $theme-name);
#if $theme{
$color: map-get($theme, $color-key );
}
#return $color;
}
#import "light";
#import "dark";
and in my theme i call it like this
.dark-theme{
$theme : dark;
#import "main";
}
in scss style file
ion-content {
color: color($theme, light);
background-color:color($theme, light);
#if($theme == 'dark'){
background-color:color($theme, primary);
}
}
Related
I'm trying to get the colors from the nuxt.config.js file and put them directly in variables.scss
Currently my variables.scss look like this
#import '~vuetify/src/styles/styles.sass';
.button-blue {
background-color: map-get($blue, darken-2) !important;
color: map-get($blue-grey, lighten-5) !important;
}
I would like to assign the color directly from nuxt.config, more or less this way:
#import '~vuetify/src/styles/styles.sass';
.button-blue {
background-color: primary!important;
color: seconday !important;
}
My nuxt.config.js
css: ['~/assets/variables.scss'],
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: false,
themes: {
light: {
primary: colors.blue.darken2,
secondary: colors.orange.darken1,
tertiary: colors.green.darken1,
accent: colors.shades.black,
error: colors.red.accent3,
info: colors.green.darken3,
background: '#EAEBEE'
},
dark: {
primary: colors.blue.darken2,
accent: colors.orange.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3,
background: colors.red.accent3
}
}
}
}
Any suggestion? I'm using Vue + Vuetify + Nuxt
Like this:
.default-box-layout {
padding: 15px;
border: 1px solid var(--v-primary);
background-color: var(--v-background);
width: 100%;
margin: 0;
}
From the docs:
Enabling customProperties will also generate a css variable for each theme color, which you can then use in your components’ blocks.
So, when you add:
theme: {
options: { customProperties: true }, // this line
},
to your Vuetify config, variables will get injected at the css root variables. Now, you can use things like --v-primary-base, like this:
.button-blue {
background-color: var(--v-primary-base);
color: var(--v-secondary-base) !important;
}
More?
See https://vuetifyjs.com/en/features/theme/#custom-properties
There are many strange errors when I using less in VSCode. Here is an example:
#library() {
.colors() {
primary: green;
secondary: blue;
}
}
#library() {
.colors() { primary: grey; }
}
.button {
color: #library.colors[primary];
border-color: #library.colors[secondary];
}
compiled file:
.button {
color: #library.colors[primary];
border-color: #library.colors[secondary];
}
line13: error: property value expectedless(css-propertyvalueexpected)
line14: error: { expectedless(css-lcurlyexpected)
line15: error: at-rule or selector expectedless(css-ruleorselectorexpected)
This is an example that I copied from http://lesscss.org on how to use map. I also noticed that map is a new feature which has been enabled since v3.5. But my LESS version is v3.10.
I need to define same style for elements under a media query and descendant by another class.
Perfect solution in LESS could be the following [pseudo-code]:
.foo
{
color:red;
.example &,
#media (min-width:800px)
{
color:blue;
}
}
that should be desirable that would be compiled into:
.foo {
color: red;
}
.example .foo {
color: blue;
}
#media (min-width: 800px) {
.foo {
color: blue;
}
}
THIS SYNTAX IS INCORRECT but, do you have some suggestion to solve my problem?
Nope, selectors and #media queries are too different language entities (despite having similar {} syntax) so you can't combine those with comma like in your example.
So to get it DRY (assuming that shared style has more than one property of course) you'll need a mixin (or sort of), for example:
.foo {
color: red;
.somename() {
color: blue;
}
.example & {.somename}
#media (min-width: 800px) {.somename}
}
Also see Passing Rulesets to Mixins examples (if you need even more generic solution).
Thanks to #seven-phases-max suggestion, I finally found a possible solution using Detached Ruleset:
#screen-xs: 480px;
#screen-sm: 769px;
#screen-md: 992px;
#screen-lg: 1200px;
.MEDIAQUERY(#only-media, #min-max, #size, #RULES)
{
#screen-width:~"#{screen-#{size}}";
#mediaQuery: ~"screen and (#{min-max}-width: #{screen-width})";
#media #mediaQuery { #RULES(); }
& when (#only-media = false) {
.#{size} & { #RULES(); }
}
}
.foo_media-and-class
{
color:red;
.MEDIAQUERY(#only-media:false, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:false, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
.foo_only-media
{
color:red;
.MEDIAQUERY(#only-media:true, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:true, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
This solution go beyond and offer other options:
Possibility to set a custom value of screen width for media query,
Pass MIN/MAX value of property used in media query (Try to pass "max" instead of "min" calling .MEDIAQUERY mixin)
Toggling generation of simple media query or media query + descendant selector, through #only-media boolean.
I think your comma might be causing the error.
.foo {
color:red;
.example & {
color:blue;
#media (min-width:800px) {
color:blue;
}
}
}
This is proper syntax to output the following:
.foo {
color: red;
}
.example .foo {
color:blue;
}
#media (min-width:800px) {
.example .foo {
color:blue;
}
}
I am trying to create a menu which is hidden but appears, fixed to the top, once the user begins scrolling down the page. So far I have managed to create a menu which sticks to the top upon scrolling but am stuck on how to hide this menu initially.
This is the code I am using so far:
(I am using wordpress-headway)
JQuery:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
//STICKY NAV
var isMobile = {
Android: function() {
return navigator.userAgent.match(/Android/i) ? true : false;
},
BlackBerry: function() {
return navigator.userAgent.match(/BlackBerry/i) ? true : false;
},
iOS: function() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
},
Windows: function() {
return navigator.userAgent.match(/IEMobile/i) ? true : false;
},
any: function() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
}
};
//Calculate the height of <header>
//Use outerHeight() instead of height() if have padding
var aboveHeight = $('.top-row').outerHeight();
//when scroll
$(window).scroll(function(){
//if scrolled down more than the header’s height but this isn't mobile
if ($(window).scrollTop() > aboveHeight && !isMobile.any()){
// if yes, add “fixed” class to the <nav>
// add padding top to the #content
// (value is same as the height of the nav)
$('.block-type-navigation').addClass('fixed').css('top','0').next()
.css('padding-top','42px');
} else {
// when scroll up or less than aboveHeight,
// remove the “fixed” class, and the padding-top
$('.block-type-navigation').removeClass('fixed').next()
.css('padding-top','0');
}
});
});
</script>
CSS:
.fixed {
position:fixed !important;
left: 0;
text-align: center;
}
.fixed .block-content {
display: inline-block;
text-align: left;
width: 940px; /* This should be the width of your grid!!! */
float:none;
}
.fixed {
position:fixed !important;
left: 0;
text-align: center;
display: block !important;
}
It's driving me crazy so I'd appreciate ANY help!
Thank you!
If you don't want the nav to show unless the user has scrolled passed a certain point then couldn't it always be fixed just off the top of the screen:
.menu {
position:fixed;
top:-42px;
}
then shown or hidden by toggling a class
.menu.is-visible {
top:0;
}
using a scroll listener.
$win = $(window);
$win.on('scroll', function() {
$(".menu").toggleClass('is-visible', $win.scrollTop() > 42);
});
You could even add some CSS animation to the top property
.menu {
-webkit-transition: top 0.2s ease-in-out;
}
to get a cool transition.
Note: All this code is typed out right in here and not tested.
Note: You should definitely put a throttle on the scroll handler too.
Hi I'm trying to learn SASS/SCSS and am trying to refactor my own mixin for clearfix
what I'd like is for the mixin to be based on whether I pass the mixin a width.
thoughts so far (pseudo code only as I will be including other mixins)
#mixin clearfix($width) {
#if !$width {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}
here's how I thought I might call it, but it's not working.
#include clearfix();
or
#include clearfix(100%)
or
#include clearfix(960px)
I'd appreciate any help on the best or right way to do this!
You can assign default parameter values inline when you first create the mixin:
#mixin clearfix($width: 'auto') {
#if $width == 'auto' {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}
You could try this:
$width:auto;
#mixin clearfix($width) {
#if $width == 'auto' {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}
I'm not sure of your intended result, but setting a default value should return false.
You could default the parameter to null or false.
This way, it would be shorter to test if a value has been passed as parameter.
#mixin clearfix($width: null) {
#if not ($width) {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}