css selectors first and last occurance [duplicate] - html

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 3 years ago.
I want to set a style on the first and last of the elements. The number of sections can vary on each odd/even, so I can not do anything like "every 3rd element then use this CSS-rule". The elements are inside one parent element, here a <div>.
What I want to achieve is that everytime the odd-section occures for the first time in this list of spans, I want to add some style, and the samme with the last occurance of odd-section. Then It begins again with the same logic for the even-section, and again for the odd-section, and then again even-section:
<div>
<span class="odd-section"></span>
<span class="odd-section"></span>
<span class="odd-section"></span>
<span class="even-section"></span>
<span class="even-section"></span>
<span class="even-section"></span>
<span class="odd-section"></span>
<span class="odd-section"></span>
<span class="odd-section"></span>
<span class="even-section"></span>
<span class="even-section"></span>
<span class="even-section"></span>
</div>
Is there a way to do this?
It would be so much better if every odd-section / even-section part had a parent <div>, but that is not the case here.

You can use the following adjacent sibling selector and first child pseudo selector to select the first of each group
If the spans are always in groups of 3s, then you could use a double adjacent for the last of each group
.odd-section:first-child,
.even-section+.odd-section {
/* this highlights the first in each group */
border: 1px solid blue;
}
.odd-section+.odd-section+.odd-section {
/* this highlights the last in each group */
border: 1px solid green;
}
<div>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
</div>
Unfortunately, if your odds and evens are not in groups of three, you will not be able to use css to select the last element of the group, instead you would either need to add a class using your server side language, or use a js approach
Below is a quick example of how you can use jquery to add a class to the last of each group
$('.odd-section').filter(function() {
return $(this).is(':last-child') || $(this).next('.even-section').length;
}).addClass('last-section');
.odd-section:first-child,
.even-section+.odd-section {
/* this highlights the first in each group */
border: 1px solid blue;
}
.last-section {
/* this highlights the last in each group */
border: 1px solid green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="even-section">even</span>
<span class="odd-section">odd</span>
<span class="odd-section">odd</span>
</div>

Related

Is it possible to have multiple span classes on the same line without using div?

I want to have each text have a different color so I used a multiple span classes to set the color in css. I also want the text to have line breaks so I used div. This fiddle shows the result I want but the div tags used for the line breaks creates a large gap. Is there another way to have line breaks with multiple span classes?
Fiddle: https://jsfiddle.net/nh7vswco/
<pre id="info">
<div class = "fact-card">
<span class="animal"> animal</span>
<span class="colon"> : </span>
<span class="animal-name">tiger</span>
<span class="comma">,</span>
</div>
<div class = "fact-card">
<span class="animal"> species</span>
<span class="colon"> : </span>
<span class="animal-name">Mammal</span>
<span class="comma">,</span>
</div>
<div class = "fact-card">
<span class="animal"> type</span>
<span class="colon"> : </span>
<span class="animal-name">carnivore</span>
<span class="comma">,</span>
</div>
Result:
Each word and colon should have a different color.
animal : tiger,
species : mammal,
type : carnivore,
This fiddle has the result Fiddle: https://jsfiddle.net/nh7vswco/ but I would like to remove the gaps from the div tag.
1- There are many ways to make a line break like so: <br> or line-break CSS property.
2- To remove the gaps from the div tag. we can use the line-height: 0%;
<style>#info {
text-align: center;
padding-left: 20px;
padding-right: 20px;
}
.colon {
color: #cc7832;
}
.animal-name {
color: #2587be;
}
.animal {
color:#9473a5;
display: block;
}
.fact-card{
display: flex;
line-height: 0%;
}
.span {
font-family: Arial;
}
<pre id="info">
<div class = "fact-card">
<span class="animal"> animal</span>
<span class="colon"> : </span>
<span class="animal-name">tiger</span>
<span class="comma">,</span>
</div>
<div class = "fact-card">
<span class="animal"> species</span>
<span class="colon"> : </span>
<span class="animal-name">Mammal</span>
<span class="comma">,</span>
</div>
<div class = "fact-card">
<span class="animal"> type</span>
<span class="colon"> : </span>
<span class="animal-name">carnivore</span>
<span class="comma">,</span>
</div>
</pre>
This issue is actually due to the side-effects of using the pre tag. The additional spacing you have in between the divs inside your pre tag are being interpreted as line breaks as that is what pre is meant to do. If you do not want this extra spacing, eliminate the extra white space (line breaks, spaces, etc.) you have.
<pre id="info"><div class = "fact-card">
<span class="animal"> animal</span>
<span class="colon"> : </span>
<span class="animal-name">tiger</span>
<span class="comma">,</span>
</div><div class = "fact-card">
<span class="animal"> species</span>
<span class="colon"> : </span>
<span class="animal-name">Mammal</span>
<span class="comma">,</span>
</div><div class = "fact-card">
<span class="animal"> type</span>
<span class="colon"> : </span>
<span class="animal-name">carnivore</span>
<span class="comma">,</span>
</div>

Semantic song markup with visual "chord stacking"

I am looking for a HTML-based representation for song texts with chords above the syllables, in the following fashion:
Am C D F
There is a house in New Orleans
Now, I don't care how exactly the HTML looks like in the end, but there is an important constraint: the purpose is not only display, but also storage in a semantically meaningful representation. Specifically, the songs are converted from a LaTeX-based syntax and should be recoverable in their original form, as well as being readable in HTML and easily processable. So no fancy structure just for the purpose of presentation, and no JavaScript (yes, I have looked at how UltimateGuitar does it, that is exactly not what I want). I need every element to have a direct correspondence to some logical part, as in the original format.
On the other hand, this gives me a hard time designing a CSS that presents the stacked chords. The basic rule is that you have "boxes" consisting of a text part and a chord part, and the width of the whole box should be the maximum of either parts, which each can consist of arbitrarily long text:
Am Cmaj7/G Am G F Am/G E7 F#sus4 A
longstuff short multichord more end. e - ternal
The boxing structure is known in advance, so you can assume it as given:
((Am) (longstuff))
((Cmaj7/G) (short))
((Am G) (multichord))
((F Am/G) (more))
end.
((E7) ())
((F#sus4 A) (e))ternal
Note that in the last box, the word is hyphenated to compensate for the two chords on the first syllable. I fear this makes it very hard for CSS, so it might be represented in a slightly different way, e.g.
((F#sus4 A) (e) (ternal))
You can come up with alternatives, as long as they still have concise semantic meaning. Here is what I have come up with so far:
.verse {
line-height: 3rem;
font-family: serif;
}
.cbox {
border: 1px solid;
}
.chord {
position: absolute;
transform: translate(0, -1.1rem);
font-weight: bold;
font-family: monospace;
user-select: none;
font-size: large;
}
<p class="verse">
Test
<span class="cbox"><span class="chord">Abc</span>X</span>
<span class="cbox"><span class="chord">Abc</span>Xyzwv</span>
<span class="cbox"><span class="chord">Abc</span>Xyzw</span>abc
sd
<br/>
Test
<span class="cbox"><span class="chord">Abc De</span>Xy</span>zwv
sd
<br/>
<span class="cbox"><span class="chord">Ab</span>xyz</span>
<span class="cbox"><span class="chord">Abc#sus4/C</span>Zyzw xyz</span>
<span class="cbox"><span class="chord">Am</span>xyzw</span>
<br/>
<span class="cbox"><span class="chord">D</span>xyz</span>
<span class="cbox""><span class="chord">E7</span></span>
two
<span class="cbox"><span class="chord">E7</span>th</span>ree
</p>
The sizes and borders are chosen for debugging. As you can see, the width of the top (chord) part is not taken into account (because position: absolute prevents that).
I have tried some other variants, including this one: <span class="cbox" data-w="2" data-c="Am">longstuff</span>, where data-w is the number of letters in the chord name to be used in the min-width of the span, and data-c being put into a before pseudo-element, but I still didn't succeed at getting the width right.
For the hyphenation issue, I have no idea at all.
And I will likely be using XHTML, although I guess this won't make much of a difference.
I'd suggest using CSS grid to help keep things from overlapping.
You can specify a grid template of 1 column and 2 rows, and then use classes to tell the content which row it should fit into. The grid will fill nicely and create implicit new columns as needed. It even will work if you have a series of chords or text in a row, without needing to wrap chord/text pairs in a wrapping element.
For the hyphenation, if possible, I'd add an additional class to syllables that need hyphenation, and then create the hyphens using a pseudo element in CSS.
Here's a working example. Hope this is helpful. This was a fun challenge.
.line {
display: grid;
justify-content: start;
grid-template-columns: auto;
grid-template-rows: auto auto;
grid-auto-flow: column;
gap: 0 0.6em;
margin-bottom: 1em;
}
.chord {
grid-row-start: 1;
}
.text {
grid-row-start: 2;
}
.hyphenated:after {
content: ' - '
}
<span class="line">
<span class="chord">Am</span>
<span class="text">longstuff</span>
<span class="chord">Cmaj7/G</span>
<span class="text">short</span>
<span class="chord">Am G</span>
<span class="text">multichord</span>
<span class="chord">F Am/G</span>
<span class="text">more</span>
<span class="text">end.</span>
<span class="chord">E7</span>
<span class="chord">F#sus4 A</span>
<span class="text hyphenated">e</span>
<span class="text">ternal</span>
</span>
<hr>
<p class="verse">
<span class="line">
<span class="chord">C</span>
<span class="text">Frosty the</span>
<span class="chord">C7</span>
<span class="text">snowman</span>
</span>
<span class="line">
<span class="text">was a</span>
<span class="chord">F</span>
<span class="text">jolly</span>
<span class="chord">F#dim</span>
<span class="text">happy</span>
<span class="chord">C</span>
<span class="text">soul</span>
<span class="chord">C7</span>
</span>
<span class="line">
<span class="text">with a</span>
<span class="chord">F</span>
<span class="text">corncob</span>
<span class="chord">F#dim</span>
<span class="text">pipe and a</span>
<span class="chord">C</span>
<span class="text">button</span>
<span class="chord">A7</span>
<span class="text">nose</span>
</span>
<span class="line">
<span class="text">and two</span>
<span class="chord">Dm7</span>
<span class="text">eyes made</span>
<span class="chord">G7</span>
<span class="text">out of</span>
<span class="chord">C</span>
<span class="text">coal.</span>
<span class="chord">C7</span>
</span>
</p>
Edit: A downside to the above approach is that the content is hard to understand if unstyled.
A more semantic approach could be to combine CSS Grid with content defined in custom data-* attributes and CSS variable fallbacks. This way the chords stay stored as attributes rather than marked-up text interspersed with the lyrics.
.verse {
line-height: 2;
}
.lyric {
display: inline-grid;
grid-template-columns: auto;
grid-template-rows: auto auto;
line-height: 1;
}
.lyric[data-chord] {
--chord: attr(data-chord);
}
.lyric:before {
content: var(--chord, '\00a0');
}
<p class="verse">
<span class="lyric" data-chord="C">Frosty the</span>
<span class="lyric" data-chord="C7">snowman</span>
<br>
<span class="lyric">was a</span>
<span class="lyric" data-chord="F">jolly</span>
<span class="lyric" data-chord="F#dim">happy</span>
<span class="lyric" data-chord="C">soul</span>
<span class="lyric" data-chord="C7"></span>
<br>
<span class="lyric">with a</span>
<span class="lyric" data-chord="F">corncob</span>
<span class="lyric" data-chord="F#dim">pipe and a</span>
<span class="lyric" data-chord="C">button</span>
<span class="lyric" data-chord="A7">nose</span>
<br>
<span class="lyric">and two</span>
<span class="lyric" data-chord="Dm7">eyes made</span>
<span class="lyric" data-chord="G7">out of</span>
<span class="lyric" data-chord="C">coal.</span>
<span class="lyric" data-chord="C7"></span>
</p>
This creates a one-column, two-row, inline grid for each .lyric span. The value of --chord is set to the value of the data-chord property only on elements that have that property. It's then used in all .lyric elements to set the content of the :before pseudo-element, with a fallback to a non-breaking space if the variable is undefined. This is important because it pushes the text into the bottom row for .lyric spans that don't have a chord, and keeps the text horizontally aligned.

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>

Hide a specific part on an HTML code via CSS [duplicate]

This question already has answers here:
Hide text in html which does not have any html tags [duplicate]
(3 answers)
Closed 2 years ago.
I am trying to hide a part of an HTML code that is not itself within a tag.
Visually this code gives : CHF120.95 - CHF152.95
Goal : Only display CHF120.95
with the help of this post I managed to hide the last part in CSS, but not the middle part (-).
p.price span:nth-child(n+2) {display:none;}
<p class="price">
<span class="wcpbc-price wcpbc-price-1357" data-product-id="1357">
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">CHF</span>
120.95
</span>
" - "
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">CHF</span>
152.95
</span>
</span>
</p>
Thanks for your help.
If visibility can be used, please see the code snippet.
p.price span:nth-child(n+2) {display:none;}
p.price {
visibility: hidden;
}
p.price > span > span {
visibility: visible;
}
<p class="price">
<span class="wcpbc-price wcpbc-price-1357" data-product-id="1357">
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">CHF</span>
120.95
</span>
" - "
<span class="woocommerce-Price-amount amount">
<span class="woocommerce-Price-currencySymbol">CHF</span>
152.95
</span>
</span>
</p>

How to Set Cursor as Pointer Via HTML Attribute

So, I am wondering how I can set the cursor as a pointer via the style HTML element attribute. Basically, how would you change the style attribute to do something upon being hovered over and then have that be cursor: pointer; rather than being in an actual CSS file (internal/external).
Here is the syntax and some examples of pointer shapes that you can specify:
<span style="cursor:auto">auto</span><br>
<span style="cursor:crosshair">crosshair</span><br>
<span style="cursor:default">default</span><br>
<span style="cursor:e-resize">e-resize</span><br>
<span style="cursor:grab">grab</span><br>
<span style="cursor:help">help</span><br>
<span style="cursor:move">move</span><br>
<span style="cursor:n-resize">n-resize</span><br>
<span style="cursor:ne-resize">ne-resize</span><br>
<span style="cursor:nw-resize">nw-resize</span><br>
<span style="cursor:pointer">pointer</span><br>
<span style="cursor:progress">progress</span><br>
<span style="cursor:s-resize">s-resize</span><br>
<span style="cursor:se-resize">se-resize</span><br>
<span style="cursor:sw-resize">sw-resize</span><br>
<span style="cursor:text">text</span><br>
<span style="cursor:w-resize">w-resize</span><br>
<span style="cursor:wait">wait</span><br>
<span style="cursor:not-allowed">not-allowed</span><br>
<span style="cursor:no-drop">no-drop</span><br>