CSS specificity for elements with more than one class - css

I am having an issue where I am unable to get the level of specificity I need to make some code work. I have a <ul> for which I want to make the backgrounds of the <li>'s change when hovered on with a fancy little slide-in animation.
I managed to get it working pretty well using a linear-gradient with a transition on :hover. I decided that I wanted to have the different list items have different background colors than each other, so I added three classes: .red, .blue, and .gold, and I figured I would just make everything with the .level1 class have the required properties other than the linear gradient itself—namely, background-size: 200% 100%, background-position:right bottom, and transition:all 1s ease, and then specify the linear gradient and color for each individual color class. I know this is all pretty intangible, but I will post my code below.
Here is what I was hoping to have (or something like it):
body .push [class^="level1"] {
background-size: 200% 100%;
background-position:right bottom;
transition:all 1s ease;
}
body .push [class^="level1"]:hover {
background-position:left bottom;
}
body .push .level1.blue {
background: linear-gradient(to right, #282e59 50%, rgba(0,0,0,0) 50%);
}
body .push .level1.red {
background: linear-gradient(to right, #94272a 50%, rgba(0,0,0,0) 50%);
}
body .push .level1.gold {
background: linear-gradient(to right, #e5d037 50%, rgba(0,0,0,0) 50%);
}
But that doesn't work. For the values in the first class to take effect, I have to get rid of the first one body .push [class^="level1"] { ... } and put that information in the three color-specific ones, like
body .push .level1.blue {
background: linear-gradient(to right, #282e59 50%, rgba(0,0,0,0) 50%);
background-size: 200% 100%;
background-position:right bottom;
transition:all 1s ease;
}
body .push .level1.red {
background: linear-gradient(to right, #94272a 50%, rgba(0,0,0,0) 50%);
background-size: 200% 100%;
background-position:right bottom;
transition:all 1s ease;
}
body .push .level1.gold {
background: linear-gradient(to right, #e5d037 50%, rgba(0,0,0,0) 50%);
background-size: 200% 100%;
background-position:right bottom;
transition:all 1s ease;
}
Is there any way to consolidate that information?

It seems the problem is not specificity, but that your shorthand background: declaration is overwriting the position & size values in your original declaration. Try changing background: to background-image: in your overwrites:
body .push .level1.blue {
background-image: linear-gradient(to right, #282e59 50%, rgba(0,0,0,0) 50%);
}
body .push .level1.red {
background-image: linear-gradient(to right, #94272a 50%, rgba(0,0,0,0) 50%);
}
body .push .level1.gold {
background-image: linear-gradient(to right, #e5d037 50%, rgba(0,0,0,0) 50%);
}

I am guessing you have html like:
...
<li class="level1">...</li>
<li class="level1 red">...</li>
<li class="level1 gold">...</li>
<li class="level1 blue">...</li>
In that case you can change your code to
.push .level1 {
background-size: 200% 100%;
background-position:right bottom;
transition:all 1s ease;
}
.push .level1:hover {
background-position:left bottom;
}
.push .blue {
background-image: linear-gradient(to right, #282e59 50%, rgba(0,0,0,0) 50%);
}
.push .red {
background-image: linear-gradient(to right, #94272a 50%, rgba(0,0,0,0) 50%);
}
.push .gold {
background-image: linear-gradient(to right, #e5d037 50%, rgba(0,0,0,0) 50%);
}

Related

CSS paramtetrized sliding background with gradient composed inline and in css file

The following HTML tag is rendering as expected statically.
style='background: linear-gradient(to right, rgba(255,255,255,0) 20%, rgba(255,255,255,1) 30%, rgba(255,255,255,1)), url(<%= image_path "/bg/#{#this_area.id}.svg" %>);'>
However, as this is being dynamically managed by a variable, and the goal is to add
#keyframes moveBg {
to {
background-position: 100% 0;
}
}
I was attempting to do the following
<div class='bg_x' style='background: url(<%= image_path "/bg/#{#this_area.id}.svg" %>);'>
and define the class
.bg_x {
background: linear-gradient(to right, rgba(255,255,255,0) 20%, rgba(255,255,255,1) 30%, rgba(255,255,255,1))
animation: moveBg 20s linear infinite;
}
However using a class plus an inline definition fails to integrate the gradient with the background image (even before adding the animation). So the inline is overriding the class, even though the instructions are complimentary.
As the CSS file cannot take variables, can this desired effect be achieved partially not inline?
Because of the Cascading in CSS the inline indeed overrules the class. Never the less. linear gradients are a part of the background-image property (shorthand background if you want to combine multiple styles, just like margin-left and margin). Normally you can separate the background-color and background-image or other elements, but with linear-gradient() that isn't possible because they both use background-image property too bad.
In the example below you can find two solution that I found. Hopefully this helps you progress this issue.
/* ClassBased */
.bg_classBased {
position: relative;
}
.bg_classBased:before {
content: "";
position: absolute;
top: 0;
left: 0;
z-index: 1;
background: linear-gradient(to right, rgba(255,255,255,0) 20%, rgba(255,255,255,1) 30%, rgba(255,255,255,1));
width: 100%;
height: 100%;
}
/* Animation */
.bg_x {
animation: moveBg 20s linear infinite;
}
#keyframes moveBg {
to {
background-position: 100% 0;
}
}
/* misc styling */
div {
padding: 40px;
}
<h1>Inline based</h1>
<div class="bg_x" style='background: linear-gradient(to right, rgba(255,255,255,0) 20%, rgba(255,255,255,1) 30%, rgba(255,255,255,1)), url("https://placehold.it/100x100");'></div>
<h1>Classbased</h1>
<div class="bg_x bg_classBased" style='background: url("https://placehold.it/100x100");'></div>

CSS Linear Gradient with Triangle starting 46%

On a wordpress website, i would like to make a header with a gradient which covers the menu in 100% but then in the breadcrumbs i would like it to be white triangle shape.
I have create a fiddle as it is quite hard to explain.
https://jsfiddle.net/hoststage/o04qfpr9/
The body CSS and the CSS class triangle header is what i'm currently running to make it work but with negative margin which I really don't like.
body {
background-color: #F4F4F4;
background-image: -moz-linear-gradient( 97deg, rgb(145,79,145) 0%, rgb(168,100,168) 100%);
background-image: -webkit-linear-gradient( 97deg, rgb(145,79,145) 0%, rgb(168,100,168) 100%);
background-image: -ms-linear-gradient( 97deg, rgb(145,79,145) 0%, rgb(168,100,168) 100%);
position: absolute;
z-index: 270;
background-repeat: no-repeat !important;
background-size:1920px 270px;
background-position: center top;
}
.triangle-header {
width:1920px !important;
height:195px;
background: linear-gradient(to top left, white 50%, transparent 0%),
transparent 0%;
margin-top: -170px
}
SO basically, i would like to start the triangle at 46% of the body gradient and merge the 2 CSS codes into the body class.
The onecodebody is my current attempt at merging the 2 properties but it doesn't work as I suspect i can't pass the argument to the bottom left inside an already defined linear.
Is there a way to define one gradient property for the body tag which would make it look like what I have in my fiddle?
Great day to you all!
Use multiple gradient like this to have transparency:
body {
height:200px;
background:
linear-gradient(rgb(145,79,145),rgb(145,79,145)) top/100% 46% no-repeat,
linear-gradient(to bottom right,rgb(145,79,145) 50%,transparent 50.5%) bottom/100% 55% no-repeat;
}
Or like this if you want to keep both colors and have the white part above to create the triangle shape:
body {
height:200px;
background:
linear-gradient(to bottom right,transparent 50%,white 50.5%) bottom/100% 55% no-repeat,
linear-gradient(97deg, rgb(145,79,145) 0%, rgb(168,100,168) 100%) top/100% 100% no-repeat;
}

Changing gradient colors of an animated background

I have an animated gradient background, and I want to override the original color by applying an other class. When I apply this new class, the animation stops.
See the code below and try to add the oc class to the div to reproduce.
.background {
background: linear-gradient(
to right,
#eee9e5 20%,
red 50%,
#eee9e5 80%
);
background-size: 400% 400%;
height: 16px;
margin: 16px 0;
}
.oc {
background: linear-gradient(
to right,
#eee9e5 20%,
blue 50%,
#eee9e5 80%
) !important;
}
.animated {
animation: move 4s ease-in infinite;
}
#keyframes move {
0%{background-position:0% 50%}
50%{background-position:100% 50%}
100%{background-position:0% 50%}
}
<div class="background animated" />
You can also see the code at https://codepen.io/Taskim/pen/KegLmJ.
Do you know any workaround to achieve that?
The problem is with the use of the !important on the background rule.
The background is a short-hand property that alters all the background-* properties.
So when you set background: linear-gradient(...)!important you override the background-position as well and setting it to default values that cannot be animated since they are more important.
Use background-image: linear-gradient(...) and it should work.
document.querySelector('button').addEventListener('click', function() {
document.querySelector('.animated').classList.toggle('oc');
})
.background {
background: linear-gradient( to right, #eee9e5 20%, red 50%, #eee9e5 80%);
background-size: 400% 400%;
height: 16px;
margin: 16px 0;
}
.oc {
background-image: linear-gradient( to right, #eee9e5 20%, blue 50%, #eee9e5 80%);
}
.animated {
animation: move 4s ease-in infinite;
}
#keyframes move {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<div class="background animated"></div>
<button>toggle gradient</button>
Also keep in mind that you cannot self-close a div (unless that is not real html but some template from a framework)

Setting linear gradient height AND width

I am aware that you can set the width of a linear gradient using
.grey-block { background: linear-gradient(to right, #f9f9f9 0%, #f9f9f9 35%, white 35%, white 100%); }
As well as the height
.grey-block { background: linear-gradient(to bottom, #f9f9f9 0%, #f9f9f9 65%, white 65%, white 100%); }
However, is there a way you can set BOTH the height and the width using a the same css line?
To clarify, the code in the question is not setting the height and width of the gradient. It's adjusting the color stops, which results in a grey rectangle.
In order to adjust the actual dimensions of the gradient, we need to use the background-size property (as well as background-repeat) to set the height and width of the gradient.
With background-size in control of the gradient's dimensions, we can rewrite the CSS to be as follows:
.grey-block {
background-color: white;
background-image: linear-gradient(#f9f9f9, #f9f9f9);
background-size: 35% 65%;
background-repeat: no-repeat;
}
What's happening is that we're defining a "gradient" of a solid color and confining it's size. The background-repeat is disabled so that it will only render a single grey block.
.grey-block {
background-color: white;
background-image: linear-gradient(#f9f9f9, #f9f9f9);
background-size: 35% 65%;
background-repeat: no-repeat;
}
/* non-relevant styles */
body {
background-color: #222;
}
.grey-block {
height: 200px;
width: 200px;
}
<div class="grey-block"></div>
You can specify an angle. That should do the trick.
.grey-block { background: linear-gradient( 135deg, #f9f9f9 0%, #f9f9f9 65%, white 65%, white 100%); }

How do I use both a CSS3 gradient and a background image

I've seen a million people do it, but I haven't been able to get it to work.
background: -webkit-linear-gradient(left top, black, #333333 85%, gray), url('/img/helix.png');
I've tried with the order reversed and with background-image, still nothing.
I saw one person use:
body:before {
content: " ";
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
left: 0;
background: -webkit-linear-gradient(left top, black, #333333 85%, gray);
}
But there has to be a better way...
Updated code:
In an ID for the image div:
height: 100%;
width: 100%;
background: transparent url('/img/helix-white.png') no-repeat;
In the CSS for the body element:
background: -webkit-linear-gradient(left top, black, #333333 85%, gray);
background: -moz-linear-gradient(left top, black, #333333 85%, gray);
background: -ms-linear-gradient(left top, black, #333333 85%, gray);
background: -o-linear-gradient(left top, black, #333333 85%, gray);
background: linear-gradient(left top, black, #333333 85%, gray);
Update 2:
I used a div with the image in it with CSS for positioning:
<div id="backgroundImage">
<img src="img/helix-white.png" alt=" " />
</div>
#backgroundImage
{
position: fixed;
bottom: 10%;
left: 7%;
opacity:0.4;
filter:alpha(opacity=40);
-webkit-transform: rotateZ(20deg);
-moz-transform: rotateZ(20deg);
-ms-transform: rotateZ(20deg);
-o-transform: rotateZ(20deg);
transform: rotateZ(20deg);
}
And in the body CSS for the gradient:
height: 100%;
background: -webkit-linear-gradient(left top, black, #333333 85%, gray);
background: -moz-linear-gradient(left top, black, #333333 85%, gray);
background: -ms-linear-gradient(left top, black, #333333 85%, gray);
background: -o-linear-gradient(left top, black, #333333 85%, gray);
background: linear-gradient(left top, black, #333333 85%, gray);
Why not have a div with the background gradient then another div inside with a background image. If the background image is a .png with transparency or doesn't fill the div, you'll be able to see the gradient behind it.
e.g.
<div id="gradient">
<div id="image">
Your content here.
</div>
</div>
CSS
#gradient {
background: -webkit-linear-gradient(left top, black, #333333 85%, gray); }
#image {
background: transparent url('your image here') center center no-repeat; }
On another note, you should use a full range of gradient options to support all browsers (not just webkit). I'd recommend using a CSS3 gradient generator for the code:
http://www.colorzilla.com/gradient-editor/
as mentioned, be sure you're checking your stuff in either Safari or an older version of Chrome. They both use(d) webkit as the rendering engine.

Resources