Suppose the following code:
<div id="body" class='bodyLogin'>
#body {
background-color: red;
}
I would like to override the background colour through the class attribute, like this:
#body .bodyLogin {
background-color: blue;
}
but this doesn't work.
Similarly:
.bodyLogin {
background-color: blue;
}
doesn't work due to CSS hierarchy.
The space between your two selectors is meaningful. In fact it is a selector: the descendant selector. It means you select all of class bodyLogin descendant of an element with id body.
Get rid of the space and you select elements that are both #body and .bodyLogin:
#body {
background-color: red;
}
#body.bodyLogin {
background-color: blue;
}
<div id="body" class='bodyLogin'>Test</div>
Related
While I know you can't write variables like
root: {
--aic: align-items:center;;
}
Is there anyway to get round this, by combining the various parts seperately? The obvious obstical here is the requirement of the colon inside the variable.
i.e.
root: {
--ai: align-items:;
--center: center;
--aic:
var(--ai)
var(--center);
}
.myclass {var(--aic);}
I would suggest you to switch to SCSS and use a #mixin. Read more about it here.
Here's a live demo.
HTML:
<div id="test">TEST</div>
SCSS:
:root {
--text_color: red;
--background_color: gold;
}
#mixin my_mixin {
color: var(--text_color);
background-color: var(--background_color);
}
#test {
#include my_mixin;
}
Based on my comment on your question, you can use classes to achieve something similar. But you can't use custom properties as CSS properties, only values -- it's the same as saying for example margin: margin: var(--customMargin);;
/* Layout unrelated to answer */
div { border: 1px solid black; color: white }
.varText { background-color: red }
.varPad { background-color: blue }
.varText.varPad { background-color: green }
/* Answer */
:root { --size: 1rem }
.varText { font-size: var(--size) }
.varPad { padding: var(--size) }
<div class="varText">
Size Text only to root variable
</div>
<div class="varText" style="--size: 2rem">
Size Text only to inline variable
</div>
<div class="varPad">
Size Padding only to root variable
</div>
<div class="varPad" style="--size: 2rem">
Size Padding only to inline variable
</div>
<div class="varText varPad">
Size Text and Padding to root variable
</div>
<div class="varText varPad" style="--size: 2rem">
Size Text and Padding to inline variable
</div>
I have two JS components, Parent and Child, each one with its own scss stylesheet. Parent pass a modifier string to Child: one or two. Child renders this modifier in its main div as a BEM modifier class:
<div className="parent">
<div className="parent__title">This is parent</div>
<div className="child child--one">
<div className="child__title">Hello, this is one</div>
<ul className="child__list">
<li className="child__item">item1</li>
<li className="child__item">item2</li>
<li className="child__item">item3</li>
</ul>
</div>
<div className="child child--two">
<div className="child__title">Hello, this is two</div>
<ul className="child__list">
<li className="child__item">item1</li>
<li className="child__item">item2</li>
<li className="child__item">item3</li>
</ul>
</div>
</div>
I want Child to be unaware of Parent, so I can not modify its style in Child.scss: has to be done in Parent.scss.
This is Parent.scss:
.parent {
$root: &;
.child--one {
color: tomato;
&__item {
color: yellow;
}
}
.child--two {
color: blue;
}
}
Here the color: yellow; rule is not applied to .parent .child--one child__item, because it is targeting .parent .child--one__item.
The question is:
without modifying the HTML structure, how can I manage to target .parent .child--one .child__item in an elegant and simple way?
I would like, if possible, to maintain .child nested inside .parent in the stylesheet, to avoid polluting the stylesheets.
I think this is the most organized way to write what you propose.
.parent {
$root: &;
.child--one {
color: tomato;
.child {
&__item {
color: yellow;
}
}
}
.child--two {
color: blue;
}
}
Note that yellow only affects .child--one items and you got to repeat .child inside .child--one in order to reuse the BEM benefits according to your classes names. For example, if you later wanna style &__title or &__list
On the other hand, if you want to reuse .child__item regardless in which child it is, you can do this:
.parent {
$root: &;
.child {
&--one {
color: tomato;
}
&--two {
color: blue;
}
&__item {
color: yellow;
}
}
}
I do not understand why pseudo classes like :focus-within need to be within the :host() function brackets when acting on the host itself. Why can it not be :host:focus-within div?
It's even more weird that it works on :host inside of another :host().
class MyElementFail extends HTMLElement {
constructor(...args) {
super(...args)
this.attachShadow({mode: 'open'}).innerHTML = `
<style>
:host{
display: block;
padding: 20px;
background-color: salmon;
}
:host div{
background-color: white;
}
/*This part is different:*/
:host:focus-within div{
background-color: green;
}
</style>
<input type="text" value="click in here"/>
<div>
Change to green
</div>`
}
}
window.customElements.define('my-element-fail', MyElementFail);
class MyElement extends HTMLElement {
constructor(...args) {
super(...args)
this.attachShadow({mode: 'open'}).innerHTML = `
<style>
:host{
display: block;
padding: 20px;
background-color: salmon;
}
:host div{
background-color: white;
}
/*This part is different:*/
:host(my-element:focus-within) div{
background-color: green;
}
</style>
<input type="text" value="click in here"/>
<div>
Change to green
</div>`
}
}
window.customElements.define('my-element', MyElement);
class MyElementTwo extends HTMLElement {
constructor(...args) {
super(...args)
this.attachShadow({mode: 'open'}).innerHTML = `
<style>
:host{
display: block;
padding: 20px;
background-color: salmon;
}
:host div{
background-color: white;
}
/*This part is different:*/
:host(:host:focus-within) div{
background-color: green;
}
</style>
<input type="text" value="click in here"/>
<div>
Change to green
</div>`
}
}
window.customElements.define('my-element-two', MyElementTwo);
No Good:
<my-element-fail></my-element-fail>
Good:
<my-element></my-element>
Good also:
<my-element-two></my-element-two>
Essentially, why does,
:host(:host:focus-within) div{ work, and
:host(my-element:focus-within) div{ work, but
:host:focus-within div{ not work?
:host is only to indicate the host element of the shadowDOM.
:host(.something) indicated the host with a class of .something.
You can not use :host.something you must use the parenthesis.
:host() is not a function. It is just how to select a :host with additional specificity.
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = `
<style>
:host{
display: block;
padding: 20px;
background-color: salmon;
}
div{
background-color: white;
}
:host(:focus-within) div{
background-color: green;
}
</style>
<input type="text" value="click in here"/>
<div>Change to green</div>`;
}
}
window.customElements.define('my-element', MyElement);
<my-element></my-element>
Actually the reason is given in Selector Level 4 specification:
The shadow host in a shadow tree is featureless and therefore cannot be matched by any pseudo-class except for :host [...].
It is illustrated in the hyperlink in the example (and actually also the link you pointed in your comment to #Intervalia's answer).
Transposed to your use case:
:focus-within doesn't match the shadow host. So, :host:focus-within which is more specific, should/could not match anything (that would be contradictory to the CSS selection fundamental).
Hence the :host() function pseudo-class that will mimic the other selectors but won't break their logic.
I have the markup:
<body class="arabic specific-page">
<div class="child">
<div class="grand-child">
</div>
</div>
</body>
In my sass I am already inside .specific-page and .child. I would like to apply a specific property if body is .arabic:
what I already have:
.specific-page {
.child{
.arabic & {
.grand-child{
gets compilet to:
.arabic .specific-page .child .grand-child
I would like to compile to:
.arabic.specific-page .child .grand-child (body has the same class)
without changing the selector at the top of the tree, only at child level
You can do this using #at-root like so:
.specific-page {
.child{
#at-root .arabic#{&} {
.grand-child{
border: 1px solid red;
}
}
}
}
This compiles to: .arabic.specific-page .child .grand-child, see here.
For this to work you're going to need to alter your SASS a bit. Try
.specific-page {
&.arabic {
.child {
.grand-child {
You could use #at-root and break out of your nesting structure.
.specific-page {
.child{
.arabic {
#at-root .arabic.specific-page .child .grand-child{}
}
}
}
I use an #mixin function like this, when i need change some element in middle
of a sass big tree.
The first parameters is the parent element, the target, and the second the class that should have.
SASS
#mixin parentClass($parentTarget, $aditionalCLass) {
#at-root #{selector-replace(&, $parentTarget, $parentTarget + $aditionalCLass)} {
#content;
}
}
Sample,
like I need to improve font size in a strong tag, when .txt-target had .txt-strong too
HTML
<section class="sample">
<h1 class="txt-target txt-bold">Sample<strong>Bold</strong>Text</h1>
</section>
SASS
section{
.txt-target{
strong{
#include parentClass('.txt-target','.txt-bold'){
font-weight:bold;
font-size:30px;
}
}
}
}
2 options:
.arabic.specific-page {
.child{
.grand-child{
Or (you can switch the order of arabic and specific-page):
.arabic{
&.specific-page {
.child{
.grand-child{
Short question: Why does the background-color of .b does not change when I hover? .a?
CSS
.a {
color: red;
}
.b {
color: orange;
}
.a:hover .b {
background-color: blue;
}
HTML
<div id="wrap">
<div class="a">AAAA</div>
<div class ="b">BBBB</div>
</div>
http://jsfiddle.net/2NEgt/
You need to have .a:hover + .b instead of .a:hover .b
.a:hover .b would work for a structure like
<div class="a">AAAA
<div class ="b">BBBB</div>
</div>
If at some point you'll need to have some elements between .a and .b, then you'll need to use .a:hover ~ .b, which works for all siblings of .a coming after it, not just the next one.
Demo http://jsfiddle.net/thebabydino/EajKf/
Can you not do something like a:hover + b? see http://meyerweb.com/eric/articles/webrev/200007a.html
You can use + selector
.a:hover + .b {
background-color: blue;
}
to apply the css for sibling element, or
.a:hover > .b {
background-color: blue;
}
for nested class.
because .b isn't a child of .a, so that selector isn't finding anything. Use javascript to do what you want to do there.
There are two things you can do.
Either change your HTML to make .b a child of .a
<div id="wrap">
<div class="a">AAAA
<div class ="b">BBBB</div>
</div>
</div>
OR
Change your css to use the adjacent selector
.a:hover + .b {
background-color: blue;
}
no js needed http://jsfiddle.net/2NEgt/3/
You shouldn't change a sibling's style when an event occurs on a different element. It's out of the context of CSS.
Use JavaScript to achieve this, for example:
var wrap = document.getElementById("wrap");
var aDiv = wrap.getElementsByClassName("a")[0];
var bDiv = wrap.getElementsByClassName("b")[0];
aDiv.onmouseover = function() {
bDiv.style.backgroundColor = "red";
};
aDiv.onmouseout = function() {
bDiv.style.backgroundColor = "white";
};
try to understanding this example:
html code
<p>Hover over 1 and 3 gets styled.</p>
<div id="one" class="box">1</div>
<div id="two" class="box">2</div>
<div id="three" class="box">3</div>
<!--css-->
#one:hover ~ #three{
background-color: black;
color: white;
}
.box {
cursor: pointer;
display: inline-block;
height: 30px;
line-height: 30px;
margin: 5px;
outline: 1px solid black;
text-align: center;
width: 30px;
}
when you hover on the box 1 than the box 3 will get black color
Jquery is a good and easy solution:
html:
<div class="a">AAA</div>
<div class="b">BBB</div>
script:
Put this script into your html if you want. That's all.
<script>
$(".a").mouseover(function(){
$(".b").css("color", "blue");
});
$(".a").mouseleave(function(){
$(".b").css("color", "red");
});
</script>