Repeated Nesting Alternating Style - html

I need the style to alternate when classes are nested in a repeating pattern. Sadly right now, all the code does is override based on the order of the CSS and not the order of the HTML.
In the example below, each word needs to be the color it names. This needs to work for an indefinite number of nestings (could be a crazy huge number of nestings), and also needs to work when other CSS styles are applied, which means that the HTML cannot be changed. Also, there is no guarantee that there won't be anything between those elements which means they won't be direct parents all the time (So the > selector will not work).
Anyone know how to do this? (Or if it is even possible?)
span {
color: black;
}
.foo a {
color: red;
}
.bar a {
color: green;
}
<html>
<body>
<span class="foo">
<span class="bar">
<span class="foo">
<span class="bar">
<span class="foo">
<span class="bar">
<strong>black green</strong>
</span>
<strong><br>black red</strong>
</span>
<strong><br>black green</strong>
</span>
<strong><br>black red</strong>
</span>
<strong><br>black green</strong>
</span>
<strong><br>black red</strong>
</span>
</body>
</html>

By putting class within a class, the proper way of calling it in CSS is through the > operator.
If the CSS is as such ( see fiddle or below), there will be a yellow and green element. This is because the CSS is only at parent/first level. I put a new line of CSS below and you see 4 red elements because it only reached until the second level CSS. The rest will follow the parent elements because they do not have any style. Therefore the closest parent that have a style defined in CSS is .bar > .foo a, resulting in red for the remaining 3 elements.
span {
color: black;
}
.foo a {
color: yellow;
}
.bar a {
color: green;
}
.bar > .foo a {
color: red;
}
Html code:
<span class="foo">
<span class="bar">
<span class="foo">
<span class="bar">
<span class="foo">
<span class="bar">
<strong>1black green</strong>
</span>
<strong><br>2black red</strong>
</span> <strong><br>3black green</strong>
</span> <strong><br>4black red</strong>
</span> <strong><br>5black green</strong>
</span> <strong><br>6black red</strong>
</span>
http://jsfiddle.net/de9ppead/

Related

how to select first child div from div parent

I have a movie card where the content is dynamic. I'm trying to select the first child DIV of the left-side-bar, however, since the content is dynamically generated, the background-color is changed to all divs.
#left-side-bar div:first-child {
background-color: #e50914 !important;
}
<div id="left-side-bar">
<h3 style="border-bottom: 1px solid red; padding-bottom: 7px">
Top 5 movies
</h3>
#foreach (var movie in Model.SidebarData.TopMovies) {
<a asp-controller="Home" asp-action="Detail" asp-route-id="#movie.Id">
<div class="card-sb">
<center><img src="#movie.ImageUrl" /></center>
<p>#movie.Title</p>
<span class="crown">
<i class="fas fa-crown" style="color: goldenrod"></i>
#movie.Views
</span>
</div>
</a>
}
</div>
The :first-child selector is intended, like the name says, to select the first child of a parent tag.
But in your example there is a tag as a parent element on the div. So if you apply nth-of-type to it, you will solve your problem. So this example will work as follows.
#left-side-bar a:nth-of-type(1) .card-sb {
background:red;
}
#left-side-bar .card-sb:first-child {
background-color: #e50914 !important;
}
<div id="left-side-bar">
<h3 style="border-bottom: 1px solid red; padding-bottom: 7px">
Top 5 movies
</h3>
#foreach (var movie in Model.SidebarData.TopMovies) {
<a asp-controller="Home" asp-action="Detail" asp-route-id="#movie.Id">
<div class="card-sb">
<center><img src="#movie.ImageUrl" /></center>
<p>#movie.Title</p>
<span class="crown">
<i class="fas fa-crown" style="color: goldenrod"></i>
#movie.Views
</span>
</div>
</a>
}
</div>
Add an Id to your div, then refer to it to change the attribute of that specific element.
<div class="card-sb" id="CardSb">
then refer to it in your style sheet:
#CardSb {background-color: #e50914}
or try this:
/* Selects every first element among any group of siblings */
#left-side-bar a:nth-child(1n) {color: #e50914;}

Block to the left, Inline to the right

I have a sequence of span elements. I need for them to display inline until an element is reach that should "wrap". The elements that follow the "wrapped" element should continue displaying inline from there. To put it another way, I want an element to display as if it was set to block with regard to the content that precedes it, but display as if it was inline with regard to the content that follows it. Consistent with performing a cr/lf.
The solution must be based on styles only. It is preferable that the only styling change be made to the "startWord" style in the sample code.
The sample below is what I currently have. Word 1, Word 2, and Word 3 should display inline, as they do. Word 4 should display down the page below Word1, as it does. Word 5 and Word 6 display down the page from Word4 due to Word4 display being set to block, but I want them to display immediately following Word4 as if Word4 display was inline or inline-block.
Any assistance would be appreciated.
<style>
.word {
border:1px solid steelblue;
}
.startWord {
border:1px solid red;
display:block; // I want something else here that allows content to display inline after it.
}
</style>
<div>
<span class="word">Word 1</span><span class="word">Word 2</span><span class="word">Word 3</span><span class="startWord">Word 4</span><span class="word">Word 5</span><span class="word">Word 6</span>
</div>
If you're able to edit the html, add a <br/> before <span class="startWord">.
If not, you can add a line break as a CSS psuedo element (as per https://stackoverflow.com/a/17048164/573718), for example before every span.startWord:
<style>
.word {
border: 1px solid steelblue;
}
.startWord {
background: red;
}
.startWord:before {
content: '\A';
white-space: pre;
}
</style>
<div>
<span class="word">Word 1</span>
<span class="word">Word 2</span>
<span class="word">Word 3</span>
<span class="word startWord">Word 4</span>
<span class="word">Word 5</span>
<span class="word">Word 6</span>
</div>
You could do that using float and clear, as I did below:
.word {
float: left;
}
.startWord{
border: 1px solid red;
float: left;
clear: left;
}
.startWord + .word {
/* here any styles for the element which follows the wrapped element could go*/
}
<div>
<span class="word">Word 1</span><span class="word">Word 2</span><span class="word">Word 3</span><span class="startWord">Word 4</span><span class="word">Word 5</span><span class="word">Word 6</span>
</div>
If needed, you can add width: 100% to .startWord to make it full width like a block.

How can I get the first matched element with a CSS selector that has different parents?

With the following HTML:
<div>
<span class="something">...</span>
<span class="something">...</span>
<span class="something">...</span>
</div>
<article>
<span class="something">...</span>
</article>
I want to find the first .something. How would I do this?
You can't achieve this with only CSS. However, JavaScript's document.querySelector can be used to obtain the first element on the page matching a selector.
const first = document.querySelector('.something');
first.style.backgroundColor = "dodgerblue";
<div>
<span class="something">...</span>
<span class="something">...</span>
<span class="something">...</span>
</div>
<article>
<span class="something">...</span>
</article>
In order to affect pseudo elements, you can add a class to the element found with document.querySelector and add another style declaration in your CSS.
const first = document.querySelector('.something');
first.classList.add("first");
.something.first:after {
content: "I'm the first one!";
color: dodgerblue;
}
<div>
<span class="something">...</span>
<span class="something">...</span>
<span class="something">...</span>
</div>
<article>
<span class="something">...</span>
</article>
It's not possible to achieve this purely with CSS. It would have been possible if all the elements with the .something class would have had the same parent (see this solution). But since they are spread over multiple parents this won't work.
You can use jQuery for this which has a :first selector:
$( ".something:first" ).css( "color", "red" );
div, article {
padding: 1em;
border: 1px solid silver;
margin-bottom: 1em;
width: 100px;
}
span { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<span class="something">Something</span>
<span class="something">Something</span>
<span class="something">Something</span>
</div>
<article>
<span class="something">Something</span>
</article>

CSS Hide outer Span and show inner span

<span class="price">as low as <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>1,335.79</span></span>
Working in WooCommerce I want to hide "as low as" which is contained in an outer span yet show the price which is contained within an inner span.
If someone could guide me as to how to do this.
Thanks
You can modify the font-size value to hide all text and then show the inner span text this way:
.price {
font-size: 0;
}
.price span {
font-size: 18px;
}
<span class="price">
as low as
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">$</span>
1,335.79
</span>
</span>
You can use visibility: hidden; on your outer <span>, and visibility: visible; on your inner <span>
.price {
visibility: hidden;
}
.woocommerce-Price-amount {
visibility: visible;
}
<span class="price">as low as <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>1,335.79</span></span>
Visibility can help you here.
.price {
visibility: hidden;
}
.price > span {
visibility: visible;
}
<span class="price">as low as
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">$</span>1,335.79</span>
</span>
If removing the space taken by the hidden text is also require then the font-size:0 is an option in some browsers provided you reset the inner text back to the required size.
.price {
visibility:hidden;
font-size:0;
}
.price > span {
visibility:visible;
font-size:1rem;
}
<span class="price">as low as
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">$</span>1,335.79</span>
</span>
Do the proper thing, and make your HTML reflect your intentions. If you want to be able to only style "as low as", then wrap that text in it's own <span> and hide that instead. This will be much cleaner than trying to select a text node with CSS and suffering from the CSS effecting the siblings also.
.hidden {
display: none;
}
<span class="price">
<span class="hidden">as low as</span>
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">$</span>
1,335.79
</span>
</span>
The best solution is to change the HTML, as in 4castle's answer.
However, if for whatever reason you cannot change the HTML structure, but you can change the text content and the CSS, and also have a way to set the class on an object as needed (I used a hacky little piece of JS to toggle, but it could also be set during generation of a static page), you can use the ::before pseudoelement to display the desired text:
function handleClick(what) {
what.classList.contains('asLowAs') ? what.classList.remove('asLowAs') : what.classList.add('asLowAs');
}
.asLowAs::before {
content: "as low as ";
}
<span class="price asLowAs" onclick="handleClick(this)">
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">$</span>
1,335.79
</span>
</span>

Select only the first and the last link in divs

I have a structure like the following:
<div class="navigation_sub_item_background" id="sub_nav_2">
<div class="navigation_sub_item" id="2_1">
<a class="navigation__sub__link" href="?p=2_1">
<span>
Test 3
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_2">
<a class="navigation__sub__link" href="?p=2_2">
<span>
Test 4
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_3">
<a class="navigation__sub__link" href="?p=2_3">
<span>
Test 5
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_4">
<a class="navigation__sub__link" href="?p=2_4">
<span>
Test 6
</span>
</a>
</div>
</div>
And I want to select only the first link and the last link. I tried div.navigation_sub_item > a.navigation__sub__link:first-of-type but this selects all of the links.
Anyone a suggestion?
Selecting the first and last link
As your links are wrapped in div elements you'll need to select the first and last div and target the first or last a element within those:
.navigation_sub_item:first-child a:first-of-type {
/* The very first link. */
}
.navigation_sub_item:last-child a:last-of-type {
/* The very last link. */
}
Note that I've specified the first-of-type and last-of-type on the a elements themselves just in case more than one a element exists within your div elements. You may want to replace these with first-child and last-child if you do not care about other elements coming before or after them.
A special case for where only one element is present
I want them all, thats cool. But what should I do if there is only one .navigation__sub__link-element? then the :last-child rule will be applied but I want another rule to be used.
In that case you can override the specificity of these selectors by specifying both first-child and last-child:
.navigation_sub_item:first-child:last-child a {
/* This will override the above selectors. */
}
Or if you're not specifying :first-of-type or :last-of-type on your a elements, you could equally use the :only-child selector:
.navigation_sub_item:only-child a {
/* This will also override the above selectors. */
}
This should work.
.navigation_sub_item:first-child .navigation__sub__link {}
.navigation_sub_item:last-child .navigation__sub__link {}
Try to this demo example here used to first-child, last-child
.navigation_sub_item:first-child .navigation__sub__link,
.navigation_sub_item:last-child .navigation__sub__link{
// here style
}
.navigation_sub_item:first-child .navigation__sub__link{
color:red;
}
.navigation_sub_item:last-child .navigation__sub__link{
color:green;
}
<div class="navigation_sub_item_background" id="sub_nav_2">
<div class="navigation_sub_item" id="2_1">
<a class="navigation__sub__link" href="?p=2_1">
<span>
Test 3
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_2">
<a class="navigation__sub__link" href="?p=2_2">
<span>
Test 4
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_3">
<a class="navigation__sub__link" href="?p=2_3">
<span>
Test 5
</span>
</a>
</div>
<div class="navigation_sub_item" id="2_4">
<a class="navigation__sub__link" href="?p=2_4">
<span>
Test 6
</span>
</a>
</div>
</div>
You can select the first and last child in the following way
.navigation_sub_item:first-child .navigation__sub__link,
.navigation_sub_item:last-child .navigation__sub__link {
/*CSS rules*/
}
You can read more about CSS3 first-child and last-child selectors
by clicking on the links.
You should use :first-child and :last-child
.navigation_sub_item:first-child a,
.navigation_sub_item:last-child a {
color: red;
}
DEMO
Try this:
.navigation_sub_item:first-child .navigation__sub__link
and
.navigation_sub_item:last-child .navigation__sub__link
to cover your comment consider this:
.navigation_sub_item:first-child .navigation__sub__link{
font-weight: bold
}
.navigation_sub_item:last-child .navigation__sub__link{
color: blue
}
<div class="navigation_sub_item_background" id="sub_nav_2">
<div class="navigation_sub_item" id="2_4">
<a class="navigation__sub__link" href="?p=2_4">Test 6</a>
</div>
</div>
i think the best method and working for me
.div-selecter a:last-of-type { color:red;}