css - set different styles to other nodes where the class applies - html

I've been trying to set different styles to the same class (when it appears for the second time in the markup) using the Subsequent-sibling combinator "~" but it seems it didn't work , maybe I'm omitting a detail with the use of "~" , also... Unfortunately I cannot change the html because it is generated by a cms
<div class="root">
<div class="container">
<div class="mosaic big">
<div>Red</div>
</div>
</div>
<div class="container">
<div class="mosaic medium">
<div>3</div>
</div>
</div>
<div class="container">
<div class="mosaic big">
<div>Blue</div>
</div>
</div>
<div class="container">
<div class="mosaic medium">
<div>4</div>
</div>
</div>
</div>
and this is the css
.root > .container > .mosaic.big {
color: red
}
.root > .container > .mosaic.big ~ .root > .container > .mosaic.big {
color: blue
}
also... here's a jsfiddle https://jsfiddle.net/chinoche/wd1rhg11/
Thanks in advance

Try this styling.
.root > .container > .mosaic.big {
color: red
}
.root > .container:nth-child(3) > .mosaic.big {
color: blue
}
OR
.root > .container > .mosaic.big {
color: red
}
.root > .container:nth-child(n+2) > .mosaic.big {
color: blue
}

From what ather answers suggested, i assumed this is what you want (you can comment if it doesn't fit edge cases):
So as i said, ~ only works with elements that have the same parent.
Note: it doesn't make it blue because it's the second .mosaic.big in a container, but because the container itself is not the first. To have a fully working solution without experimental features, you should need JS
CSS:
.root > .container > .mosaic.big {
color: red
}
.root > .container ~ .container > .mosaic.big {
color: blue
}
https://jsfiddle.net/wd1rhg11/5/

Sadly without changing the html you will not be able to use the subsequent sibling selector
The CSS next sibling selector will only match the immediate siblings of the class to the left of the operator. So for this to work the elements you use with this operator must have the same parent.
In addition the matching on the right hand side will begin at the element matched on the left hand side therefore you dont need to add the parent structure
.root > .container > .mosaic.big {
color: red
}
.root > .container > .mosaic.big ~ .mosaic.big {
color: blue
}
See updated
https://jsfiddle.net/wd1rhg11/4/
You may be able to acheive what you are trying to with javascript if possible

You can use nth-child(n) of '.mosaic' class:
.root > .container > .mosaic:nth-child(1).big {
color: red;
}
.root > .container > .mosaic:nth-child(3).big {
color: blue;
}
here`s jsfiddle
https://jsfiddle.net/andrewsilent/w8jjjsbz/

Related

Select child css without a specific element

I want to apply css style in all mat-tab-group element without impacting the style of app-form element
<div class="area">
<childhere></childhere>
<mat-tab-group>
<mat-tab *ngFor="..." [label]="label">
<form [formGroup]="formGroup">
<div class="inside-tab">
<mat-form-field>...</mat-form-field>
<mat-form-field>...</mat-form-field>
<mat-form-field>...</mat-form-field>
<mat-form-field>...</mat-form-field>
</div>
<app-form></app-form>
</form>
</mat-tab>
</mat-tab-group>
</div>
I've try using :not property but it's not working
mat-tab-group > mat-tab > form :not(:last-child){
background-color: #009926; //to test
}
Any suggestions?
mat-tab-group > mat-tab > form {
background-color: #009926; //to test
}
mat-tab-group > mat-tab > form:last-child {
background-color: unset;
}
This way, last child background will fallback to default.
stackblitz example
Snippet:
div > div > * {
background-color: blue;
color: white
}
div > div > *:last-child {
background-color: green;
}
<div>
<div>
<p>first</p>
<p>secont</p>
<p>last</p>
</div>
</div>

CSS - Only select the first descendant

I'm trying to style all my main tags based on a certain theme.
If a section's class is red, all of of it's inner tags should use the red style regardless of if that section is inside another section which uses the yellow style.
So my question is how do I restrict the inner tags of a section/div/nav etc, to only use the style of the first descendant it encounters.
Note: I do not want to rely on the order of which I declare my tags.
.red input {
background-color: red;
}
.red article {
background-color: red;
}
.red p {
background-color: red;
}
/*.. other tags.. */
.yellow input {
background-color: yellow;
}
.yellow article {
background-color: yellow;
}
.yellow p {
background-color: yellow;
}
/*.. other tags.. */
.blue input {
background-color: blue;
}
.blue article {
background-color: blue;
}
.blue p {
background-color: blue;
}
/*.. other tags.. */
<section class="yellow">
<section class="blue">
<form>
<input type="button" value="This should use the blue theme" />
</form>
</section>
<section class="red">
<article>
<p>This should use the red theme</p>
<!-- This is instead yellow, how do I fix that? -->
</article>
</section>
<section class="yellow">
<nav>
<p>This should use the yellow theme</p>
</nav>
</section>
<p>This should be yellow.</p>
</section>
UPDATE
Okay so I've tried the given solutions and they work with the given example but as soon as I expand the html code to something more complex it doesn't work anymore.
The thing is that since I have to build a general theme, I cannot use css rules that depend on the order of how the html is built. A user should be able to build its website and regardless of how the html is built the correct styles should be applied.
So if the user gives a container tag (nav, section, div, aside, etc.) the class dark-theme, yellow-theme or whatever other theme, all of its children should use that style UNLESS a child container has also specified its own theme.
Is it just not possible? :(
Ex:
section class=yellow-theme
p: use yellow-theme
aside: use yellow-theme
div class=red-theme
ul: use red-theme *not yellow
p: use red-theme *not yellow
footer class=blue-theme
a: use blue-theme *not red not yellow
h3: use blue-theme *not red not yellow
div class=yellow-theme
header: use yellow-theme *not blue * not red
form: user yellow-theme *not blue *not red
<!--This could go on forever and in any order with any tags-->
css:
.yellow-theme anytag{
/* Style any attributes needed: borders, colors, fonts, margins, paddings, etc. */
}
/* Do this for all the tags that needs to be styled */
.red-theme anytag{
/* Style any attributes needed: borders, colors, fonts, margins, paddings, etc. */
}
/* Do this for all the tags that needs to be styled */
.blue-theme anytag{
/* Style any attributes needed: borders, colors, fonts, margins, paddings, etc. */
}
/* Do this for all the tags that needs to be styled */
Any selector-only solution requires you to make assumptions about your markup that may or may not be within your control since the specificity of two contextual selectors is always the same regardless of how close the ancestor is to each descendant that is matched, and any solution that makes use of inheriting the actual properties themselves requires you to apply them to the .red, .yellow and .blue sections, which may not be desired. For example, you'd have to apply background-color to the sections in order for background-color: inherit to work on the descendants, but you may not want the sections themselves to have any background color, so that won't be an option to you.
Custom properties allow descendants to inherit values from their closest ancestors without polluting other properties in this manner, and without other cascading rules getting in the way (competing rules with equally specific contextual selectors, etc). You'll only be able to do this reliably with custom properties for this reason.
.red {
--color: red;
}
.yellow {
--color: yellow;
}
.blue {
--color: blue;
}
input, article, p {
background-color: var(--color);
}
<section class="yellow">
<section class="blue">
<form>
<input type="button" value="This should use the blue theme" />
</form>
</section>
<section class="red">
<article>
<p>This should use the red theme</p>
</article>
</section>
<section class="yellow">
<nav>
<p>This should use the yellow theme</p>
</nav>
</section>
<p>This should be yellow.</p>
</section>
This porblem is a little bit difficult if you want to solve it with all elements.
You have to think the other way: NOT "a rule is valid until there is another rule" BUT "the closest rule is valid".
How to achieve this?
First set a rule for all elements that are grandchildren except the form tag (perhaps also the ol, ul, nav, ... tags) that the background-color shell inherit. Now all this elements inherit theire background-color from the parent element.
Second set one rule for each theme that defines the background-color of all direct children. Here you have to take a look at the problem with the form tag. the form tag has no inheritage (see above) so the children of the form will not get the rule from the closest theme parent. So you have to setup an extra rule for this case.
All in all:
*.color * > *:not(form):not(html):not(body) {
background-color:inherit!important;
}
.red > *:not(form):not(.color), .red > form > *:not(.color) {background-color: red!important}
.yellow > *:not(form):not(.color), .yellow > form > *:not(.color) {background-color: yellow!important}
.blue > *:not(form):not(.color), .blue > form > *:not(.color) {background-color: blue!important}
(.color is a css class that all sections have, that also have the css class .red or .yellow or .blue)
the > - signs are important
you can mix up all the rules.
EDIT Now I see that !important is not neccessary :)
You can also write
*.color * > *:not(form):not(html):not(body) {
background-color:inherit;
}
.blue > *:not(form):not(.color), .blue > form > *:not(.color) {background-color: blue}
.red > *:not(form):not(.color), .red > form > *:not(.color) {background-color: red}
.yellow > *:not(form):not(.color), .yellow > form > *:not(.color) {background-color: yellow}
EDIT2 if you want to style a specific tag in a theme, you have to add the rules in the following way.
1) Add all css attributes that you want to style to the first rule of the set:
*.color * > *:not(form):not(html):not(body) {
background-color:inherit;
color:inherit;
}
2) replace the asterisk by the tag name
.blue > *:not(form):not(.color), .blue > form *:not(.color) {background-color: blue}
.red > *:not(form):not(.color), .red > form *:not(.color) {background-color: red}
.yellow > *:not(form):not(.color), .yellow > form *:not(.color) {background-color: yellow}
.blue > input:not(form):not(.color), .blue > form input:not(.color) { color:white; }
.red > input:not(form):not(.color), .red > form input:not(.color) { color: green; }
.yellow > input:not(form):not(.color), .yellow > form input:not(.color) { color: purple; }
3) have a look at the > - signs! I removed it at one position to make it work with all tags.
To target only the direct descendant of an element, you can use the direct descendant operator: >:
.red > input {
background-color: red;
}
And to go one step better, you can replace all repetitions like so, instead of having to manually declare each element:
.red > * {
background-color: red;
}
.yellow > * {
background-color: yellow;
}
.blue > * {
background-color: blue;
}
Try This :
.yellow > *:not(form):not(section), .yellow form * {background-color: yellow !important}
.blue > *:not(form):not(section), .blue form * {background-color: blue !important}
.red > *:not(form):not(section), .red form * {background-color: red !important}
.yellow > *:not(form):not(section), .yellow form * {background-color: yellow !important}
.blue > *:not(form):not(section), .blue form * {background-color: blue !important}
.red > *:not(form):not(section), .red form * {background-color: red !important}
<section class="yellow">
<section class="blue">
<form>
<input type="button" value="This should use the blue theme" />
</form>
</section>
<section class="red">
<article>
<p>This should use the red theme</p>
<!-- This is instead yellow, how do I fix that? -->
</article>
</section>
<section class="yellow">
<nav>
<p>This should use the yellow theme</p>
</nav>
</section>
<p>This should be yellow.</p>
</section>
Not sure if I understand your question, so just comment if I'm wrong.
Increase the specificity of the style so that will not be overridden that easily.
.red > article > p {
background-color: red;
}
.red input {
background-color: red;
}
.red article {
background-color: red;
}
.red > article > p {
background-color: red;
}
/*.. other tags.. */
.yellow input {
background-color: yellow;
}
.yellow article {
background-color: yellow;
}
.yellow p {
background-color: yellow;
}
/*.. other tags.. */
.blue input {
background-color: blue;
}
.blue article {
background-color: blue;
}
.blue p {
background-color: blue;
}
/*.. other tags.. */
<section class="yellow">
<section class="blue">
<form>
<input type="button" value="This should use the blue theme" />
</form>
</section>
<section class="red">
<article>
<p>This should use the red theme</p>
<!-- This is instead yellow, how do I fix that? -->
</article>
</section>
<section class="yellow">
<nav>
<p>This should use the yellow theme</p>
</nav>
</section>
<p>This should be yellow.</p>
</section>
I tried this and it works, regardless of what element is it as long as you define the parent, hope this helps
body > :first-child
{
background-color: #ff0000;
}

How can I color text in <p> that it contains in a <div>

How to color a text in a <p> that it contains in a <div> when the user hovers with the mouse.
Suppose I have this html code:
<div id="riga_ristorante_1" >
<div>
<p>HI</p>
</div>
<div><p>HOME</p></div>
<div><p>DOG</p></div>
</div>
I want color the "hi","HOME","DOG" in black when the user go on the <p> element, so I use CSS:
#riga_ristorante_1:hover > p {
text-align: center;
color: black;
}
But it doesn't work. Anyone can help me?
You are using a child combinator (a greater than sign: >), but the div with the id your selector matches is the grandparent of the paragraphs, not the parent.
Use a descendant combinator (a space: ) instead.
You are targeting the paragraph directly after your ID div which in your html you don't have a paragraph tag that is a immediate child of your riga_ristorante_1
for more info on > selector
https://developer.mozilla.org/en/docs/Web/CSS/Child_selectors
With your given html you can do
#riga_ristorante_1:hover p { ... }
or
#riga_ristorante_1:hover div > p { ... }
or
#riga_ristorante_1 div:hover > p { ... }
or even
#riga_ristorante_1 p:hover { ... }
css selector will be riga_ristorante_1:hover > div > p {}
#riga_ristorante_1:hover > div > p {
text-align: center;
color: blue;
}
<div id="riga_ristorante_1" >
<div>
<p>HI</p>
</div>
<div><p>HOME</p></div>
<div><p>DOG</p></div>
</div>
You have your p as second level in deep, so you can't use > as it applies to first level only. Use
#riga_ristorante_1:hover p {
color: red;
}
#riga_ristorante_1:hover p {
color: red;
}
<div id="riga_ristorante_1" >
<div>
<p>HI</p>
</div>
<div><p>HOME</p></div>
<div><p>DOG</p></div>
</div>
Try with #riga_ristorante_1 p:hover just give toggle effect
#riga_ristorante_1 p:hover {
text-align: center;
color: blue;
}
<div id="riga_ristorante_1" >
<div>
<p>HI</p>
</div>
<div><p>HOME</p></div>
<div><p>DOG</p></div>
</div>
Leave the HTML Code but change your css selector to #riga_ristorante_1 div > p:hover then set your preferred styles
HTML Code
<div id="riga_ristorante_1" >
<div><p>HI</p></div>
<div><p>HOME</p></div>
<div><p>DOG</p></div>
</div>
The css selector should be #riga_ristorante_1 div > p:hover so the css will look like below and add more styles if you like like the text-align in the original css code.
CSS Code
#riga_ristorante_1 div > p:hover {
color: blue;
}

Change content of div:before on mouse over another div is not working

I follow this example
https://stackoverflow.com/a/19122409/2761794
Please view this jsfiddle
http://jsfiddle.net/rflfn/pZr3c/
HTML:
<!-- This Works -->
<div class='container'>Mouse Over Here!</div>
<div class='test'>
<div class='text'></div>
</div>
<br />
<!-- This not Work -->
<div class="container1">
<div class='container2'>Mouse Over Here2!</div>
</div>
<div class='test2'>
<div class='text2'></div>
</div>
CSS:
/* This Works */
.test .text:before{
content: 'Text2 Normal';
color: red;
}
.container:hover ~ .test .text:before{
content: 'Text2 Hover';
color: green;
}
/* -------- */
.test2 .text2:before{
content: 'Text2 Normal';
color: red;
}
/* This not Work */
.container1 .container2:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}
/* This not Works too */
/*.container2:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}*/
First Example works perfecly, but second example dont work. I need use this with div inside div, but works only if div the div has not within another div. What's wrong? I would like if possible to use only css to do this.
.container1 .container2:hover ~ .test2 .text2:before
It doesn't work because .container2 isn't a sibling element of .test2. Its parent, .container1, is a sibling therefore the following would work:
(~ is a general sibling combinator - it only looks at sibling elements.)
.container1:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}
I'm afraid what you're trying to do isn't possible in pure CSS since you can't transverse the DOM and there are no parent selectors present. You would need JS to do that.

Show div when hover another div using only css

I have searched the web for this one but didn't find anything similar.
Say we have div A and div B. When hover on div A, div b should be visible ON (should look like overwriting) div A and not placed under.
It should appear like only the content of div A has changed to content of div B.
How can this be done in pure CSS and HTML?
#container > div {
display: none
}
#container > div:first-child {
display: block
}
#container > div:hover + div {
display: block
<div id="container">
<div>A</div>
<div>B</div>
</div>
This will work, but only if the two divs are adjacent and b follows a.
#a:hover + #b {
background: #f00
}
<div id="a">Div A</div>
<div id="b">Div B</div>
If you have divs in between use ~
#a:hover ~ #b {
background: #f00
}
<div id="a">Div A</div>
<div id="c">Div C</div>
<div id="b">Div B</div>
To go the other way around, unfortunately you will need Javascript
// Pure Javascript
document.getElementById('b').onmouseover = function(){
document.getElementById('a').style.backgroundColor = '#f00';
}
document.getElementById('b').onmouseout = function(){
document.getElementById('a').style.backgroundColor = '';
}
// jQuery
$('#b').hover(
function(){$('#a').css('background', '#F00')},
function(){$('#a').css('background', '')}
);
Full fiddle http://jsfiddle.net/p7hLL/5/
If you don't want to use the selector + or ~ which aren't compatible with some browsers, it is just possible if the <div /> to show (e.g. div#b) is a child of the <div /> to hover (e.g. div#a).
<div id="a">
<div id="b"></div>
</div>
<style>
div#b {
display: none;
}
div#a:hover div#b {
display: block;
}
</style>
Its works, but your css should be like this
<style>
#b{display:none;}
div#a:hover div#b{display:inline}
</style>