How to combine two SCSS selectors? - css

I want to give a different color to the element if either of the two conditions exists.
Here is the code:
.btn-link{
color: $color-black;
margin: 0;
&:hover{
color: $color-light-blue;
}
&:not(.collapsed){
color: $color-light-blue;
}
}
Everything is good, but it will be better if you can combine the two selectors
I already tried:
&:hover&:not(.collapsed){
color: $color-light-blue;
}
But only the hover is identified

Same way as you do in CSS:
&:hover, &:not(.collapsed) {
color: $color-light-blue;
}
This sets the color only if the element is in a hover state or doesn't have the class collapsed.

You can put a comma between the two combining selectors, like this: &:hover, &:not(.collapsed) {
Full example:
HTML:
<span class="btn-link">one class</span>
<span class="btn-link collapsed">two class</span>
CSS:
$color-black: black;
$color-light-blue: lightblue;
.btn-link {
color: $color-black;
margin: 0;
&:hover, &:not(.collapsed) {
color: $color-light-blue;
}
}
JSfiddle.
Sorry, no StackSnippet. We still can't handle SCSS here!

You can try this simple change your code
/*SCSS*/
$color-light-blue : red;
.btn-link {
&:hover:not(.collapsed) {
color: $color-light-blue;
}
}
/*compiled CSS*/
.btn-link:hover:not(.collapsed) {
color: red;
}
<span class="btn-link">one class</span>
<span class="btn-link collapsed">two class</span>

Related

CSS attribute from body element used on other classes?

I am trying to create a basic CSS template for a project. It needs to support both a light and dark mode.
In the html, the body tag has data-layout-color attribute. I have some toggles that allow switching between light and dark, and it is updating this attribute. In my CSS sheet, I use the attribute selector for background color, and it works! Now I need to be able to set other elements color based on the light/dark mode, but that's not working as the individual element doesn't have the attribute. I don't want to add data-layout-color to everything, and then have to update it all with my js. Any suggestions?
HTML:
<body ng-controller="myApp" data-layout-color="dark" data-layout="topnav">
<button type="button" class="btn btn-primary">PRESS ME!</button>
</body>
CSS:
body[data-layout-color="dark"]{
background-color: var(--my-body-dark-bg);
}
body[data-layout-color="light"]{
background-color: var(--my-body-light-bg);
}
.btn-primary[data-layout-color="light" {
color: var(--my-white-light);
background-color: var(--my-primary-light);
border-color: var(--my-primary-light);
}
.btn-primary[data-layout-color="dark" {
color: var(--my-white-dark);
background-color: var(--my-primary-dark);
border-color: var(--my-primary-dark);
}
You could write your selectors such that the attribute selector remains on body:
/* primary button under a "light" layout parent */
[data-layout-color="light"] .btn-primary {
color: var(--my-white-light);
background-color: var(--my-primary-light);
border-color: var(--my-primary-light);
}
But I think a better idea would be to change the custom property values so you don't need the theme-specific selectors on child elements in the first place:
[data-layout-color="dark"] {
--button-color-bg: white;
--button-color-fg: black;
}
[data-layout-color="light"] {
--button-color-bg: black;
--button-color-fg: white;
}
.btn-primary {
background-color: var(--button-color-bg);
color: var(--button-color-fg);
display: inline-block;
padding: 0.25em 1em;
border: 1px solid grey;
margin: 0.5em;
}
<div data-layout-color="dark">
<div class="btn-primary">Dark Body</div>
</div>
<div data-layout-color="light">
<div class="btn-primary">Light Body</div>
</div>
With plain css you can write it like this
body[data-layout-color="dark"]{
background-color: var(--my-body-dark-bg);
}
body[data-layout-color="dark"] .btn-primary{
color: var(--my-white-dark);
background-color: var(--my-primary-dark);
border-color: var(--my-primary-dark);
}
body[data-layout-color="dark"] .btn-primary a{
text-decoration: underline overline #FF3028;
}
I suggest you use scss though. It will make your life easier. If you'r using visualstudio code just download Live sass complier and click watch sass in the bottom right corner.
Using scss you would write it like this:
body[data-layout-color="dark"]{
background-color: var(--my-body-dark-bg);
.btn-primary{
color: var(--my-white-dark);
background-color: var(--my-primary-dark);
border-color: var(--my-primary-dark);
a{
text-decoration: underline overline #FF3028;
}
}
.btn-secondary{
color: var(--my-white-dark-secondary);
background-color: var(--my-primary-dark-secondary);
border-color: var(--my-primary-dark-secondary);
}
p{
color: var(--my-white-dark);
}
}
body[data-layout-color="light"]{
background-color: var(--my-body-light-bg);
/*etc etc*/
}

Styling links syntax for CSS

.button a:link {
color: blue;
}
.button a:visited {
color: purple;
}
.button a:hover {
color: red;
}
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
<button>Derbyshire</button>
<button>Devon</button>
</div>
The links do not change color when selected. I have also tried:
btn-group a:link {color:blue} etc. but again that wording doesn't work.
What wording should I use?
If by "selected" you mean that they have focus, you can add a selector for :focus.
Also note that your buttons are children of the links, not vice versa, as your CSS rules imply, so you have to turn that around; plus button is a tag, not a class, therefore it shouldn't have a preceding dot in a CSS selector.
a:link button {
color: blue;
}
a:visited button {
color: purple;
}
a:hover button {
color: red;
}
a:focus button {
color: green;
}
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
<button>Derbyshire</button>
<button>Devon</button>
</div>
.button is targeting an element with a class of "button", to target an element itself you would just use button. It probably makes more sense to target .btn-group instead of applying styles to all button's. It's also good to be specific, by adding that this only applies to button elements within .btn-group that are direct children of a tags.
You can set all the buttons within an a tag (:link) to be blue, and then set all buttons within an a tag that have been visited to be purple, and then set all buttons to be red on hover.
.btn-group a:link > button {
color: blue;
}
.btn-group a:visited > button {
color: purple;
}
.btn-group a > button:hover {
color: red;
}
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
<button>Derbyshire</button>
<button>Devon</button>
</div>
Your CSS is wrong. You are trying to style an element with the class button and you are targeting an a element inside of that element. You don't need the button elements at all.
You should target .btn-group a. That basically means an a element inside of your .btn-group div.
.btn-group a:link {
color: blue;
}
.btn-group a:visited {
color: purple;
}
.btn-group a:hover {
color: red;
}
<div class="btn-group">
Cambridgeshire
Cornwall
Cumbria
Derbyshire
Devon
</div>
Notes:
:link - Styles the link in its normal state.
:visited - Styles the link once it has been visited by a user
:hover - Styles the link as the user hovers.
:active - this is a temporary state as the user is actively engaging, e.g. holding down the mouse button on click.
.btn-group a:link > button {
color: blue;
}
.btn-group a:visited > button {
color: purple;
}
.btn-group a:hover > button{
color: red;
}
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
<button>Derbyshire</button>
<button>Devon</button>
</div>
I know I don't need the buttons, but that's how I want the links to appear and not merely with the name.
It doesn't appear to make any difference whether I use
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
or
<div class="btn-group">
<button>Cambridgeshire</button>
<button>Cornwall</button>
<button>Cumbria</button>
I have changed the CSS to:
.btnn-group a:link { color: blue;
}
.btn-group a:visited { color: purple;
}
.btn-goup a:hover { color: red;
}
.btn-group a:active { color: red;
}

CSS Variables - Swapping values?

I have a very simple problem with CSS variables. I would like to swap two CSS variables, basically the CSS equivalent of [a, b] = [b, a] in ES6. Here's a simple example:
<p>White background</p>
<button>Black background</button>
<div>
<p>Black background</p>
<button>White background</button>
</div>
:root {
--primary-color: #fff;
--secondary-color: #000;
}
body {
background-color: var(--primary-color);
}
button {
background-color: var(--secondary-color);
}
div {
/* i'd like to do the following: */
--primary-color: var(--secondary-color);
--secondary-color: var(--primary-color);
/* so here, `--primary-color` would be `--secondary-color` from `:root`
* and any children have these colors swapped as well
*/
background-color: var(--primary-color);
}
However, this fails because CSS var()s are live bindings. Am I missing something here? Or is this the way the spec currently works?
You are creating a cyclic dependence because you are defining each property using the other one and this won't work. Instead you may try something like this by introducing more variables:
:root {
--p:#fff;
--s:#000;
--primary-color: var(--p);
--secondary-color: var(--s);
}
body {
background-color: var(--primary-color);
}
button {
background-color: var(--secondary-color);
}
div {
/* i'd like to do the following: */
--primary-color: var(--s);
--secondary-color: var(--p);
background-color: var(--primary-color);
}
<p>White background</p>
<button>Black background</button>
<div>
<p>Black background</p>
<button>White background</button>
</div>

Update CSS Module variables from Javascript

I'm using a (now older) version of react-boilerplate which came with CSS Modules. What's nice about them is that you can create variables and import them in other CSS files.
Here's my colors.css file
:root {
/* Status colors */
--error: #842A2B;
--success: #657C59;
--pending: #666;
--warning: #7E6939;
}
When I'm importing that file I just have to use at the top of my .css file:
#import 'components/App/colors.css';
I'm looking to have the option for two themes for my website and I would like to be able to dynamically update those variables with Javascript. What's the best way to do this?
Edit: I was hoping there's a way to update the colors.css file and not have to do conditional imports in all the components that draw from two possible css files... let me know if there's a way to do that and if there is I'll change the accepted answer. Thank you to all who answered!
I would just use the default color vars on the element/body/whatever, then put the alternate theme colors in another class, and toggle the theme class via JS. Here's a demo.
$("button").on("click", function() {
$("body").toggleClass("foo");
});
body {
--red: red;
--blue: blue;
--yellow: yellow;
background: #ccc;
text-align: center;
font-size: 5em;
}
.foo {
--red: #ce1126;
--blue: #68bfe5;
--yellow: #ffd100;
}
.red {
color: var(--red);
}
.blue {
color: var(--blue);
}
.yellow {
color: var(--yellow);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="red">RED</span> <span class="blue">BLUE</span> <span class="yellow">YELLOW</span>
<br>
<button>click me</button>
I would have 2 sheets and conditionally switch between the two:
colours.scss
:root {
/* Status colors */
--error: #842A2B;
--success: #657C59;
--pending: #666;
--warning: #7E6939;
}
otherColours.scss
:root {
/* Status colors */
--error: #FF0000;
--success: #00FF00;
--pending: #6666FF;
--warning: #FF00FF;
}
then in your react code import them and use them as you wish:
import styles from 'colours.scss';
import alternativeStyles from 'otherColours.scss';
...
{this.props.useNormalStyle ? styles.myClass : alternativeStyles.myClass}
Is this what you are looking for?
// get the inputs
const inputs = [].slice.call(document.querySelectorAll('.controls input'));
// listen for changes
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));
function handleUpdate(e) {
// append 'px' to the end of spacing and blur variables
const suffix = (this.id === 'base' ? '' : 'px');
document.documentElement.style.setProperty(`--${this.id}`, this.value + suffix);
}
:root {
--base: #ffc600;
--spacing: 10px;
--blur: 10px;
}
body {
text-align: center;
}
img {
padding: var(--spacing);
background: var(--base);
-webkit-filter: blur(var(--blur));
/* 👴 */
filter: blur(var(--blur));
}
.hl {
color: var(--base);
}
/*
misc styles, nothing to do with CSS variables
*/
body {
background: #193549;
color: white;
font-family: 'helvetica neue', sans-serif;
font-weight: 100;
font-size: 50px;
}
.controls {
margin-bottom: 50px;
}
a {
color: var(--base);
text-decoration: none;
}
input {
width:100px;
}
<h2>Update CSS Variables with <span class='hl'>JS</span></h2>
<div class="controls">
<label>Spacing:</label>
<input type="range" id="spacing" min="10" max="200" value="10">
<label>Blur:</label>
<input type="range" id="blur" min="0" max="25" value="10">
<label>Base Color</label>
<input type="color" id="base" value="#ffc600">
</div>
<img src="http://unsplash.it/800/500?image=899">
<p class="love">😘</p>
<p class="love">Chrome 49+, Firefox 31+</p>

Is it possible to use adjacent selector with less

I wonder if I can use the adjacent selector in LESS. Here's a piece of code :
HTML
<input id="my-input" type="text" class="my-class"/>
<label for="my-input" />
LESS
.my-class {
display: none;
&+label {
color: red;
}
}
I'm getting an error when compiling this LESS code. It says Unrecognized Input at line XX (&+label)
Any ideas ?
EDIT
Actually I get this error when I add one more nested rule like this :
.my-class {
display: none;
&+label {
color: red;
&:hover {
background-color: grey;
color: blue;
}
}
}
I don't if this is a bug or not.

Resources