CSS Grab All Class Name Except For Last - css

I want to grab all the class name ('my-class') and change it's color to red EXCEPT for the last one
Apparently I've been googling and there's no such thing as :last-of-class or whatever. I'm having trouble trying to find a work around without using JS.
div1 and div2 are both dynamic! If div2 doesn't exist, then div1 should have the first p element red and the second not.
Please note I left a 'p' tag at the top because I don't want that being part of my selector. I just need the 'my-class' specifically.
or is there a selector I can write to grab all "p"s inside of my-container which include nested P's
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class"></p>
<p class="my-class"></p>
</div>
<div class="div2">
<p class="my-class"></p>
<p class="my-class"></p>
<p class="my-class"></p>
<p class="my-class"></p> <!-- This tag should not be red-->
</div>
</div>
I can also use sass so feel free to include that in if need be.

I don't know of any SINGLE rule that would do this, but a simple workaround would be to use 2 separate rules in conjunction:
.my-class {
color: red;
}
.div-2 .my-class:last-child {
color: // whatever you want the default to be
}
note that the order is important, setting the last child's color should be done after setting everything first

You can use the workaround below.
use div:last-child . that will select the last div in the container and if there is only one, it will select it and so...the last p from the last div will be of other color ( in this example )
.my-container div p.my-class {
color:red;
}
.my-container div:last-child p.my-class:last-child {
color:blue;
}
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class">a</p>
<p class="my-class">a</p>
</div>
<div class="div2">
<p class="my-class">a</p>
<p class="my-class">a</p>
<p class="my-class">a</p>
<p class="my-class">b</p> <!-- This tag should not be red-->
</div>
</div>

This will get the behavior you're looking for without any forced reflow:
.my-class:not(:last-child) {
color: red;
}
<p>Some text</p>
<div class="my-container">
<div class="div1">
<p class="my-class">a</p>
<p class="my-class">b</p>
</div>
<div class="div2">
<p class="my-class">c</p>
<p class="my-class">d</p>
<p class="my-class">e</p>
<p class="my-class">f</p> <!-- This tag should not be red-->
</div>
</div>

Related

How to style paragraphs

I have 5 paragraphs in my div and I need to style them differently.
Is there an easier way to do it rather than giving each paragraph a different class?
<div class="container-fluid">
<div class="row">
<div class="col bg-dark text-white">
<p class="text">Nikolina Tute 2 Mount Street, Manchester M2 5WQ</p>
<p class="text-2">#1 in Customer Service in the UK</p>
<p class="text-3">Free Shipping for Orders over 60$</p>
<p class="text-4">support#hlfonline.co.uk</p>
<p class="text-5">07441 430 469</p>
</div>
</div>
</div>
Just make a standard class and then make micro classes for the changes you want:
<p class="p-class"> Some Text </p>
<p class="p-class"> Some Text </p>
<p class="p-class diff-class"> I'm Different!! </p>
.p-class{
background: green;
text-align: center;
font-size: 1rem;
}
.diff-class{
"Some different stuff here"
}
If you don't want to write in the class name for each paragraph than you can replace ".p-class" with just "p" Keep in mind this will affect all "p" elements.
I'm aware these aren't good class-naming conventions.
Generally speaking, if each P tag needs to be accessed differently. Then yes you will need to put an ID/Class selector on each p tag. You can either use an ID on each p tag or do some type of subclasses in CSS and take advantage of the cascading effect.
.base{
color: green;
}
.firstP{
color:red
}
.lastP{
color: purple;
}
<div>
<p class="base firstP">Some text</p>
<p class="base">Some text</p>
<p class="base">Some text</p>
<p class="base">Some text</p>
<p class="base lastP">Some text</p>
</div>
Another thing you could do if you wanted to have cleaner markup in the HTML is nth-child selector. This way you HTML doesn't have a bunch of classes on it and all the work is done in the CSS file
#base p{
color: green;
}
#base p:nth-child(1){
color: red;
}
#base p:nth-child(5){
color: purple;
}
<div id="base">
<p >Some text</p>
<p >Some text</p>
<p >Some text</p>
<p >Some text</p>
<p >Some text</p>
</div>

CSS: Change child on parent hover (only single child)

I can change child on parent hover like this:
.parent:hover .child{ ... }
Problem is, that this will change all childs in document.
(I'm using parent 10x on the page => it will change childs in all these parent)
Is there a CSS way, how to change only child of the parent, that I'm currently hovering over?
Example:
<div class="parent">
<p class="child"></p>
</div>
<div class="parent">
<p class="child"></p>
</div>
<div class="parent">
<p class="child"></p>
</div>
If I hover over first .parent, I want change on its .child. But my mentioned solution will affect all childs.
You'll want to directly select the child using the ">" or the "adjacent sibling combinator"
.parent:hover > .child{
background: red;
}
<div class="parent">
<p class="child">child one</p>
</div>
<div class="parent">
<p class="child">child two</p>
</div>
<div class="parent">
<p class="child">child three</p>
</div>

CSS - first-child selector not working

I am using bulma as css framework, and have a section on my page where I am looping over items, and creating multiline columns.
<section class="section employees">
<div class="container">
<div v-for="(value, key) of employeesGroupedByDepartments">
<div class="columns is-multiline department">
<div class="title-with-line">
<h4><span>{{ key }}</span></h4>
</div>
<div class="employee column is-3" v-for="employee of value">
<div class="card">
<figure class="image is-96x96">
<img :src="employee.image.data.path" alt="">
</figure>
<h4 class="title is-5">
{{employee.title}}
</h4>
<h6 class="subtitle is-6">
<small>
{{getExtras(employee, 'position')}}
</small>
</h6>
</div>
</div>
</div>
</div>
</div>
</section>
I would like to remove left padding for each first child column, I have tried with setting even to both classes padding left 0 as important but nothing worked:
.employees {
.column:first-child, employee:first-child {
padding-left: 0!important;
}
}
What am I doing wrong?
A .column will never be a first-child, because there is always a div.title-with-line before it.
From MDN:
The :first-child CSS pseudo-class represents the first element among a group of sibling elements.
You would need the :nth-child or :nth-of-type selector.
.column is not the first child as you have a div with class title-with-line proceeding it. What you're looking for is:
.employees {
.column:nth-child(2), .employee:nth-child(2) {
padding-left: 0!important;
}
}

Nested first-of-type and first-letter

I'm trying to add a drop-cap feature using css selectors first-of-type and first-letter.
This is for a WordPress site and the issue I'm having is that some posts could be build using visual composer while others could be built using the standard editor.
That means that the inner html structure of the content changes (divs are added) and my css rule .post_content > p:first-of-type:first-letter { font-size: 24px } doesn't work any more.
<div class="post_content">
<p>Hello world</p>
<p>Another line</p>
<p>Another line</p>
<p>This shouldn't be dropcaped</p>
<p>Another line</p>
<p>Another line</p>
</div>
becomes
<div class="post_content">
<div class="vc_row wpb_row vc_row-fluid">
<div class="wpb_column vc_column_container vc_col-sm-12">
<div class="vc_column-inner">
<div class="wpb_wrapper">
<div class="wpb_text_column wpb_content_element ">
<div class="wpb_wrapper">
<p>Hello world</p>
<p>Another line</p>
<p>Another line</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="vc_row wpb_row vc_row-fluid">
<div class="wpb_column vc_column_container vc_col-sm-12">
<div class="vc_column-inner">
<div class="wpb_wrapper">
<div class="wpb_text_column wpb_content_element ">
<div class="wpb_wrapper">
<p>This shouldn't be dropcapped</p>
<p>Another line</p>
<p>Another line</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
If i remove the immediate children selector (>) all paragraphs get the style applied.
Is there something I'm missing ? Is there any way I could achieve the desired effect ?
Thanks!
PS: Actually, the simplified version works, I just tested it in a fiddle. But the real html is this:
https://jsfiddle.net/s8ajo1hw/
and you can see the issue with the <p> tag being selected multiple times.
PPS: After a bit of fiddling, I found out that the issue was from p nested in separate divs that are nested in the main post_content. Simplified version: https://jsfiddle.net/9v9j3amz/
As you can see from the fiddle, the behaviour is quite weird.
Any insight on why this happens is much appreciated!
Just use:
.post_content:first-letter{
font-size:34px;
color: red;
}
The complex query was not working because :first-letter applies the style on the first letter from the selector.
I hope it helps you to achieve desired effect. Add this CSS to your stylesheet..
div.post_content * > p:first-of-type:first-letter {
font-size: 24px;
}
It will select all nested elements no matter how many. This asterisk * is a wildcard here.
Update:
I have tinkered a bit with your code but actually there are way too many nested elements and they can grow. So if you don't mind javascript add this snippet to the end of your file. Will solve your problem pretty good for now. Work on your both fiddles.
<style>
.my-class:first-letter {
font-size: 60px;
}
</style>
<script>
var el = document.getElementsByClassName("wpb_wrapper")[0].getElementsByTagName("p")[0];
el.className = 'my-class';
</script>
Since ::first-letter applies to the "first letter of the first line of a block-level element" you can just target the .post_content:
.post_content:first-letter {
font-size: 48px;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/::first-letter
demo: https://codepen.io/anon/pen/KqZYgy

Apply CSS rule to multiple elements within a sub-class

I have the following markup:
<div class="class-XXX">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
For simplicity, lets assume that class-XXX can only have the values class-1, class-2, class-3 and class-4.
I want to apply the rule color: #fff; to every child of class-5 that is not a child of class-1. Here that part of my stylesheet:
.class-2 .class-5,
.class-3 .class-5,
.class-4 .class-5 {
color: #fff;
}
This is not working and I'm not really sure why. I don't believe that the rule is being overridden either.
UPDATE
As AndrewBone pointed out, the rule appears to work in a minimal example. I now understand what is wrong, but I don't know how to fix it:
There is a rule being applied to h1 in another CSS file (can't be removed) and that rule is being given higher priority than the rule I was writing. How can I fix this?
Here is an example JSFiddle.
SOLUTION
Vucko pointed out that the h1 type selector has higher priority and so the rule will not be applied. So, in order to avoid listing all possible combinations one should use the * selector!
End result:
.class-2 .class-5 *,
.class-3 .class-5 *,
.class-4 .class-5 *{
color: #fff;
}
My thanks to Paulie_D and David Wilkinson for teaching me about the :not pseudo-selector.
This would do it..
[class^="class-"]:not(.class-1) .class-5 {
*/ your styles here */
}
...but this only works for a specific methodolody in classnames as above.
[class^="class-"]:not(.class-1) .class-5 {
color: red;
}
<div class="class-1">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-2">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-3">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-4">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-5">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
If you have some container for those divs, you can then use the :not selector (as Harry mentioned in the comment):
.main :not(.class-1) .class-5 {
color: red;
}
<div class="main">
<div class="class-1">
<div class="class-5">
<!-- could be any text element -->
<h1>1</h1>
</div>
</div>
<div class="class-2">
<div class="class-5">
<!-- could be any text element -->
<h1>2</h1>
</div>
</div>
<div class="class-3">
<div class="class-5">
<!-- could be any text element -->
<h1>3</h1>
</div>
</div>
<div class="class-4">
<div class="class-5">
<!-- could be any text element -->
<h1>4</h1>
</div>
</div>
<div class="class-5">
<div class="class-5">
<!-- could be any text element -->
<h1>5</h1>
</div>
</div>
</div>
.main :not(.class-1) .class-5 {
color: red;
}
JSFiddle
This does the trick: https://jsfiddle.net/023rox1k/
CSS:
.wrapper :not(.class-1) .class-5 {
color: blue;
}
HTML:
<div class="wrapper">
<div class="class-1">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-2">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-3">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
<div class="class-4">
<div class="class-5">
<!-- could be any text element -->
<h1>Content</h1>
</div>
</div>
</div>
The :not selector is quite powerful and obviously targets elements not of a certain class in this case.

Resources