I imported a third party CSS (which I'm not allowed to modify) into my application. This CSS file is declaring a class name and a selector, e.g.:
.third-party-class{
color: blue;
}
.third-party-class:last-of-type{
color: red;
}
My goal is to remove the .third-party-class:last-of-type selector completely by using CSS only. Of course you could just override the .third-party-class:last-of-type selector and copy every property from .third-party-class. But this is really inconvenient if .third-party-class has a lot of properties.
.third-party-class{
color: blue;
}
.third-party-class:last-of-type{
color: red;
}
.desired-li{
color: blue;
}
<div>
Currently:
<ul>
<li class="third-party-class">one</li>
<li class="third-party-class">two</li>
<li class="third-party-class">three</li>
</ul>
Desired:
<ul>
<li class="desired-li">one</li>
<li class="desired-li">two</li>
<li class="desired-li">three</li>
</ul>
</div>
Question
Is it possible to override/remove a CSS selector completely, without redeclaring all properties of the "base" class by using CSS (no JS) only?
Since we are dealing with last-of-type and you cannot change the CSS, you can add an extra element that will trigger this selector and hide it (I suppose you are able to adjust the HTML):
.third-party-class {
color: blue;
}
.third-party-class:last-of-type {
color: red;
background:pink;
font-size:250px;
opacity:0.9;
display:flex;
vertical-align:sub;
/*doesn't matter what CSS you will have here*/
}
ul li:last-of-type {
display:none!important;
}
<ul>
<li class="third-party-class">one</li>
<li class="third-party-class">two</li>
<li class="third-party-class">three</li>
<li></li>
</ul>
I agree with the comment that BenM made to your original question.
But...If the CSS is as simple (only one line) as your fiddle leads me to believe you could just use "!important" on the selector you want to overwrite.
.third-party-class:last-of-type{
color: blue !important;
}
That would allow you, on a selector by selector basis (assuming there are more than just color being used), specify what you want the third party code to do.
You could use the [attribute^=value] Selector, it will overide every ellement who starts with "value" so you can make something like this:
.third-party-class{
background: blue;
height: 20px;
width: 20px;
margin-bottom: 10px;
}
.third-party-class:last-of-type{
background: red;
}
div[class^="third-party-class"]{
background: green;
}
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
<div class="third-party-class"></div>
Sorry if i do not understand it right
Related
How can I change the style of another element when a link is hovered - without jQuery/ JavaScript?
ul>li>a:hover main {
opacity: 0.1;
}
main p {
font-size: 200px;
}
<header>
<ul>
<li>Hover me</li>
</ul>
</header>
<main>
<p>Hello World!</p>
</main>
I want to change the opacity of the text in main when the link is hovered.
Is it possible?
EDIT
I tried with a sibling:
a:hover ul {
opacity: 0.5;
}
<header>
<ul>
<li>Hover me<span></span>
<ul>
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
</ul>
</header>
But still does not work...
It's possible but the layout must be situated differently due to CSS cascading behavior. Whatever you hover over (call it the trigger) and whatever is fading because of the hover (call it target) must have specific positions in order for it to work.
Trigger -
Can be before target as an "older" sibling.
OR
Can be an ancestor of target or a sibling of an ancestor of target.
Demo
a {
border: 3px dotted blue;
padding: 0 5px;
color: #000;
text-decoration: none;
display: block;
}
a.aunt {
border-color: red;
margin: 10px 0;
}
a.aunt:hover+main p {
opacity: 0.1;
transition: 1s;
}
a.brother:hover+p {
color: red;
}
a.sister:hover~p {
color: blue;
}
main.mom {
border: 5px dashed tomato;
}
main.mom p {
opacity: 1;
font-size: 50px;
margin-top: 10px;
transition: 1s;
border: 3px solid red;
}
main.mom:hover p {
font-size: 100px;
}
b {
font-size: 25px
}
<a href='#/' class='aunt'>Aunt - Older sibling of an ancestor of the target</a>
<main class='mom'>
<a href='#/' class='sister'>Big Sister - Sibling to target with <br>sibling combinator: <b>~</b></a><br><br>
<a href='#/' class='brother'>Big Brother - Adjacent Sibling to target with <br>adjacent sibling combinator: <b>+</b></a>
<p>Target</p>
<a href='#/' class='brother'>Little Brother - Cannot influence target when hovered on.</a>
<br> Mom - hovering over affects all descendants<br>(i.e. all siblings and siblings' and target's descendants)<br>
</main>
<a href='#/' class='aunt'>Aunt - This is after target's ancestor so it cannot influence target</a>
In general, this type of problem is solved using combinators.
In this specific case, you need a parent combinator, which does not exist in CSS, so it is impossible without restructuring the HTML (e.g. to make the <main> a sibling of the <a>).
It is not possible to use + or ~ sibling selectors, becouse <a> and <main> elements are not siblings. Thus you could use JavaScript. For example it is possible using by fadeTo() within hover() method:
$("a[data-opacity-target]").hover(function() {
var selector = $(this).data("opacity-target");
$(selector).fadeTo(500, 0.1);
}, function() {
var selector = $(this).data("opacity-target");
$(selector).fadeTo(500, 1);
});
main p {
font-size: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
<ul>
<li>Hover me</li>
</ul>
</header>
<main>
<p>Hello World!</p>
</main>
In your EDIT section you should use a:hover~ul selector instead of a:hover ul.
Really interesting question.
You can try out the following code:
.trigger{
color: black;
}
div:hover ~ .trigger{
color: orange;
}
div{
display: inline-block;
border: 1px solid green;
border-radius: 10px;
padding: 5px;
width: auto;
}
<!DOCTYPE html>
<html>
<head>
<title>Pure CSS event handling</title>
</head>
<body>
<div>Hover over me for pure CSS events</div>
<p class="trigger">Hey Pikachu!</p>
</body>
</html>
Take a look at this link, it explains about the tilde selector in CSS:
what-does-the-tilde-squiggle-twiddle-css-selector-mean
I personally thought this was not possible. I learnt something new today! :D
This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 7 years ago.
I am try to skip hidden child while using nth-child(odd) and nth-child(even), but it does not skip those hidden records.
i have the following HTML and CSS code.
<style>
ul {
list-style-type: none;
}
li {
height: 2em;
border: 1px solid black;
}
/* li:not(.hidden):nth-child(odd) { */
li:nth-child(odd) {
background: khaki;
}
li:nth-child(even) {
background: indianred;
}
.hidden {
display: none;
}
</style>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li class="hidden">4</li>
<li class="hidden">5</li>
<li class="hidden">6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
</ul>
I want to list displaying on the browser should have alternative color irrespective of the number of hidden children.
If you could change your document's structure, then you could set a different tag for the hidden items, so that you could take advantage of the :nth-of-type pseudo-class:
CSS:
div.list p {
height: 2em;
border: 1px solid black;
margin: 0;
}
div.list p:nth-of-type(odd) {
background: khaki;
}
div.list p:nth-of-type(even) {
background: indianred;
}
.hidden {
display: none;
}
HTML:
<div class="list">
<p>1</p>
<p>2</p>
<p>3</p>
<span class="hidden">4</span>
<span class="hidden">5</span>
<span class="hidden">6</span>
<p>7</p>
<p>8</p>
<p>9</p>
<p>10</p>
<p>11</p>
</div>
As this answer explains there is currently no way to do this purely with CSS. You could work around this by altering the code that hides the li elements so that it inserts a another hidden dummy element after the hidden item to even things out and make it look right, and then remove that dummy item when you un-hide it.
var hide = function (el) {
el.classList.add('hidden');
el.insertAdjacentHTML('afterend', '<li class="hidden dummy"></li>');
},
show = function (el) {
if (el.classList.contains('hidden')) {
el.classList.remove('hidden');
el.parentNode.removeChild(el.nextElementSibling);
}
};
Working fiddle here
You will need to remove the hidden elements from the DOM, rather than just hide them.
I was looking into ways to optimize css performance and was wondering if their is an existing tool that converts complicated selectors to more simplistic ones.
The tool would look at all css rules and create unique single-pathed selectors that would contain all the proper attributes. It would than looked at every dom node and search for any css matches, and if something is found it would add the simplified selector to the node. The css that is rendered only contains the simplified versions and the html would still have the original classes/ids so the existing setup wouldn't break.
An exaggerated example of what I mean:
#original {
padding: 5px;
background: blue;
}
#original .nav {
font-size: 24px;
}
#original .nav ul {
background: black;
}
#original .nav ul li {
list-style-type: none;
}
#original .nav ul li a {
text-decoration: none;
color: green;
}
#simplified {
padding: 5px;
background: blue;
}
._ranClass1 {
font-size: 24px;
}
._ranClass2 {
background: black;
}
._ranClass3 {
list-style-type: none;
}
._ranClass4 {
text-decoration: none;
color: green;
}
<div id="original">
<h1>Original CSS</h1>
<div class="nav">
<ul class="_ranClass2">
<li>Link 1
</li>
<li>Link 1
</li>
<li>Link 1
</li>
</ul>
</div>
</div>
<div id="simplified">
<h1>Simplified CSS</h1>
<div class="nav _ranClass1">
<ul class="_ranClass2">
<li class="_ranClass3">Link 1
</li>
<li class="_ranClass3">Link 1
</li>
<li class="_ranClass3">Link 1
</li>
</ul>
</div>
</div>
Of course this would require heavy tweaking and may cause more headaches than good, but was wondering if something like this exists.
EDIT:
I am not looking at a way to write more convenient CSS, SASS/SCSS exists for that reason. I am looking for a way to optimize CSS in terms of the browser.
EX: take the original selector
#original .nav ul li a {
text-decoration: none;
color: green;
}
simplified too
._ranClass4 {
text-decoration: none;
color: green;
}
Instead of the browser looking at every 'a' node, then checking to make sure the parents match, it just matches if the node has class ._ranClass4
I would avoid what you're doing in your example. Your selectors should not be too wordy, but it's also nice for them to have some level of description so you know what their intended purpose is.
You may want to read into BEM and other CSS methodologies that can help organize and speed up writing your CSS.
You're also probably looking for something like CSSO or another gulp/grunt task. CSSO has a feature you expressly desired, to parse your markup and remove useless selectors from your CSS. Be wary, if you have DOM modifiers in some JS scripts, you might run into issues where CSSO removes these selectors from your CSS because, at the time the task was run, they didn't exist in your markup.
Here is a good article on other methods of CSS optimization.
An initial CSS styling cannot be overwritten by a style specificly assigned to it. How shall I structure my CSS or how can I style the nested element with blue type correctly?
js fiddle
HTML
<ul class="listing">
<li>
<p> There is plenty of wood.</p>
</li>
<li>
<div class="big">
<p> This is extra big</p>
</div>
</li>
</ul>
CSS
.listing li p{
font-size: 1em;
color: red;
}
.big p {
font-size: 2em;
color: blue;
}
You may try this (Example)
div.big p {
font-size: 2em;
color: blue;
}
it's all about specificity, check this article as well.
Update : Also you can be more specific like this
.listing li div.big p {
font-size: 2em;
color: blue;
}
While the answer you just accepted works, I'd recommend against using CSS selectors like that.
Not only do they slow down the page load when you begin to scale your site, it's bad practice in general. (Read Writing efficient CSS selectors, Code smells in CSS) You should be using the most efficient, straight-forward CSS selectors, and not giving yourself a gigantic headache by targeting descendants after descendants after descendant.
Here is a more minimal solution:
HTML
<ul class="listing">
<li>
<p> There is plenty of wood.</p>
</li>
<li>
<p class="big">This is extra big</p>
</li>
</ul>
CSS
.listing p {
font-size: 1em;
color: red;
}
.listing .big {
font-size: 2em;
color: blue;
}
http://jsfiddle.net/BKLrS/4/
Although I'd very much recommend taking this further and doing this: http://jsfiddle.net/BKLrS/5/
Markup:
<li class="divider"></li>
<li class="active">Home
<li class="divider"></li>
<li>Blog</li>
How do I add a style the first .divider only if .active is the next sibling?
I was thinking of .divider + .active but that would apply styles to .active.
.divider {
border-left: 1px solid #d0d0d0;
}
.active {
background: #fff;
}
// when the next sibling is .active, border-color: transparent;
You cannot select a previous element in CSS as of now, what you can do is either manually target the class by providing some distinct class to it like
<li class="divider target_me"></li>
And than simply use
ul.class_name li.target_me {
/* Styles goes here */
}
Else, if it's the first child of li
You can use ul.class_name li:first-child, if it's not, simply use nth-of-type(n), substitute n with the nth number of your li, this way you don't need to call classes too.
For example
ul.class_name li:nth-of-type(2) {
/* Styles here */
}
The above selector will select 2nd child of ul element with that specified class name.
Still not happy with CSS? You can opt for JS/jQuery solution, but if the markup is static, I would suggest you to use nth and if you have access to markup you can atleast call class on the element you want to style..
Note: You cannot nest li tag as a direct child to li, consider changing your markup to below ..
<ul>
<li>
Home
<ul>
<li>Sub</li>
</ul>
</li>
</ul>
This could work for you:
div {
color: black;
float: right;
}
.active + div {
color: pink;
}
<div class='third'>third</div>
<div class='second active'>second</div>
<div class='first'>first</div>
Fiddle
CSS doesn't have direct support for this as of now, but jQuery makes it relatively painless, and assuming this is a requirement for your project, could well be the way to go.
In jQuery it would be written something like this:
if element.next().hasClass('active'){
element.addClass('divider')
Here's a Fiddle
CSS
.divactive {
border-left: 1px solid transparent;
}
jQuery
$(function() {
$('.active').prev('.divider').addClass('divactive');
//or
$('.active').prev('.divider').css({ 'border-left': '1px solid transparent' });
});