Can't figure out why CSS work like this - css

How come the #r3 isn't pink? (see jsfiddle.net/aAqKf/):
<!DOCTYPE HTML>
<html>
<head>
<style>
#r1 { width: 100px; height: 100px; border: solid 1px red; }
#r2 { width: 50px; height: 50px; border: solid 1px green; }
#r3 { width: 25px; height: 25px; border: solid 1px blue; }
.pink div {
background: pink;
}
.red div {
background: red;
}
</style>
</head>
<body>
<div id="r1" class="red">
<div id="r2" class="pink">
<div id="r3"></div>
</div>
</div>
</body>
</html>
I would expect the pink class to apply the pink background to the div children. It doesn't work like that. Why?
Though, it works if I change the CSS as follows (jsfiddle.net/aAqKf/1/):
<style>
#r1 { width: 100px; height: 100px; border: solid 1px red; }
#r2 { width: 50px; height: 50px; border: solid 1px green; }
#r3 { width: 25px; height: 25px; border: solid 1px blue; }
.red div {
background: red;
}
.pink div {
background: pink;
}
</style>
Please help me figure out how come it works that way. Also, please do not suggest that I use !important along with the background: pink declaration because it will work only until I change the HTML as follows:
<div id="r1" class="pink">
<div id="r2" class="red">
<div id="r3"></div>
</div>
</div>
NB: I am more interested in figuring out why it works that way than finding out how to make it work my way.

Both rules .pink div and .red div are equally specific. The latter rule overrides the former.
You almost never have to use !important, by the way. Using the selector body .pink div, or div.pink div is enough to give the selector more weight.

From this page
To make it easy, when two rules have the same weight, the last rule specified wins.
In your first fiddle, the red wins. In the second the pink wins.

Because the properties of class inheritance differ from that of the actual element.
For example, if you changed
.pink div { background: pink; }
to:
#r2 div { background: pink; }
it would work as you intended it, because the nested block level elements inherit based on their closest parent.
Classes, on the other hand, have much looser inheritance and properties get overwritten based on the parents, unless specifically said otherwise using !important, when two selectors have the same weight.
To further demonstrate this point, changing .pink div to div.pink div would also demonstrate the correct effect because, again, CSS is referring to an element and not a class selector.

Related

After-Before pseudo in CSS3 for multiple classes

How to assign after & before pseudo classes to multiple CSS-classes
For example:
[class*="divclass-"]::before, ::after{
border-radius: 50%;
width: 30%;
height : 30%;
border: 3px solid red;
}
Consider this HTML structure, where you have a <div> which have children <span> and <p>. And another <span> and <p> as siblings.
<div>
<span>abc</span>
<p>xyz</p>
</div>
<span>123</span>
<p>456</p>
For example, if we need to change the colour of the children, we could write on your way,
div span, p{
color: red;
}
This problem with this is that, it will change the colour of the sibling <p>456</p> too as the style is applied globally to all the paragraph tags.
And the solution is to follow specificity as we did with the <span> and write the selectors as
div span,
div p{
color: red;
}
The same rule applies to pseudo-elements as well. Hence the solution is,
[class*="divclass-"]::before,
[class*="divclass-"]::after{
border-radius: 50%;
width: 30%;
height : 30%;
border: 3px solid red;
}
Note 1
If you are working on SASS, your syntax could be,
[class*="divclass-"]{
&::before,
&::after{
border-radius: 50%;
width: 30%;
height : 30%;
border: 3px solid red;
}
}
Note 2
The before and after pesudo-elements require the content property.
Hope this helps.
The comma does not mean that the following elements are children of the same selector (here [class*="divclass-"]).
It just allows you to chain the selectors.
#see https://www.thoughtco.com/comma-in-css-selectors-3467052
Here is the solution:
[class*="divclass-"]::before,
[class*="divclass-"]::after {
border-radius: 50%;
width: 30%;
height : 30%;
border: 3px solid red;
content: '';
}
<div class="divclass-1" style="height: 10px; width: 10px"></div>

Can you combine CSS declarations?

You can combine CSS selectors by using a comma, such as in the following example:
.one, .two {
color: #F00;
}
<div class="one">One</div>
<div class="two">Two</div>
This has the same result as specifying the two selectors independently:
.one {
color: #F00;
}
.two {
color: #F00;
}
<div class="one">One</div>
<div class="two">Two</div>
Combining selectors as above is incredibly useful, as it means that you only have to worry about changing one value if you want to alter multiple elements. This comes in really handy for colour scheme changes.
But is it possible to combine CSS declarations?
For example, let's say I'm trying to vertically centralise text in an element, where line-height should always equal height:
.test {
border: 1px solid #000;
padding-left: 10px;
height: 100px;
line-height: 100px;
}
<div class="test">Test</div>
The expected combined declaration of height, line-height: 100px; doesn't apply either declaration, raising an invalid property value.
In SASS, it would be possible to make line-height dependent on height with something as simple as:
$height = 100px;
.test {
border: 1px solid #000;
padding-left: 10px;
height: $height;
line-height: $height;
}
Is there any way to specify that one property should utilise the same value from another property with raw CSS?
Sure you can:
:root {
--height: 100px;
}
.test {
border: 1px solid #000;
padding-left: 10px;
height: var(--height);
line-height: var(--height);
}
<div class="test">Test</div>
But not all browsers support CSS variables - http://caniuse.com/#feat=css-variables

Is there a CSS selector for an IMG which has been constrained by max-width or max-height?

If I define the following CSS rule:
img {
max-width: 200px;
max-height: 200px;
border: 1px solid black;
}
Is there a pure-CSS way of detecting those image objects that would have been larger without the size constraints? Something that semantically matches:
img:resized {
border-color: green;
}
Alternatively: is there a way of only detecting large images in the first place? For example:
img {
border: 1px solid black;
}
img[width>200px], img[height>200px] {
max-width: 200px;
max-height: 200px;
border-color: green;
}
Thanks!
No, there are no CSS selectors that can query style properties, whether declared or computed, as rendering of DOM elements has no relation to the DOM hierarchy.

CSS - Rollover one element, and make another element visible

In CSS, is it possible that when I rollover one element, I make another element visible? I have an icon, and when someone mouses over it, I want it to make visible a text element that describes what the icon does.
Here's a CSS only tooltip I use all the time :) Works great, even in IE.
a:hover {
background:#ffffff;
text-decoration:none;
}
/*BG color is a must for IE6*/
a.tooltip span {
display:none;
padding:2px 3px;
margin-left:8px;
width:130px;
}
a.tooltip:hover span{
display:inline;
position:absolute;
background:#ffffff;
border:1px solid #cccccc;
color:#6c6c6c;
}
Easy
<a class="tooltip" href="#">
Tooltip
<span>T his is the crazy little Easy Tooltip Text.
</span>
</a>
Hope it helps.
You can make child-elements visible by hovering on the parent (as Hunter suggests), or siblings:
span:hover + span {display: block; }
There are maybe some slight cross-browser compatibility issues, but with a valid doctype I think IE7+ is okay with sibling selectors (though I've not tried to test that theory).
sure it is!
.me:hover span { display: block; }
If you want to show an element that isn't a child of the element hovered you might need to use javascript
Here's a little slapped-together example that won't work on IE...
<html>
<head>
<style>
div.tooltip
{
margin-top: 16px;
margin-left: -1px;
position: absolute;
border: 1px solid black;
background-color: blue;
color: yellow;
display: none;
}
div.icon
{
width: 16px;
height: 16px;
border: 1px solid blue;
background-color: cyan;
}
div.icon:hover .tooltip
{
display: block;
}
</style>
</head>
<body>
<div class="icon">
<div class="tooltip">This is what the icon does.</div>
</div>
</body>
</html>
But you really should just use jQuery.
Agree with the JavaScript recommendation. Specifically jQuery is easy and most appropriate for page behavior logic. I think CSS should only be look/feel/style...Javascript should be were all your event and behavior logic is.

How can I fix an issue in IE where borders don't show up when the mouse isn't hovered over an image

I am trying to create a rather simple effect on a set of images. When an image doesn't have the mouse over it, I'd like it to have a simple, gray border. When it does have an image over it, I'd like it to have a different, "selected", border.
The following CSS works great in Firefox:
.myImage a img
{
border: 1px solid grey;
padding: 3px;
}
.myImage a:hover img
{
border: 3px solid blue;
padding: 1px;
}
However, in IE, borders do not appear when the mouse isn't hovered over the image. My Google-fu tells me there is a bug in IE that is causing this problem. Unfortunately, I can't seem to locate a way to fix that bug.
Try using a different colour. I'm not sure IE understands 'grey' (instead, use 'gray').
The following works in IE7, IE6, and FF3. The key was to use a:link:hover. IE6 turned the A element into a block element which is why I added the float stuff to shrink-wrap the contents.
Note that it's in Standards mode. Dont' know what would happen in quirks mode.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<style type="text/css">
a, a:visited, a:link, a *, a:visited *, a:link * { border: 0; }
.myImage a
{
float: left;
clear: both;
border: 0;
margin: 3px;
padding: 1px;
}
.myImage a:link:hover
{
float: left;
clear: both;
border: 3px solid blue;
padding: 1px;
margin: 0;
display:block;
}
</style>
</head>
<body>
<div class="myImage"><img src="http://stackoverflow.com/Content/Img/stackoverflow-logo-250.png"></div>
<div class="myImage"><img src="http://stackoverflow.com/Content/Img/stackoverflow-logo-250.png"></div>
</body>
</html>
In my experience IE doesn't work well with pseudo-classes. I think the most universal way to handle this is to use Javascript to apply the CSS class to the element.
CSS:
.standard_border
{
border: 1px solid grey;
padding: 3px;
}
.hover_border
{
border: 3px solid blue;
padding: 1px;
}
Inline Javascript:
<img src="image.jpg" alt="" class="standard_border" onmouseover="this.className='hover_border'" onmouseout="this.className='standard_border'" />
Try using the background instead of the border.
It is not the same but it works in IE (take a look at the menu on my site: www.monex-finance.net).
<!--[if lt IE 7]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script>
<![endif]-->
put that in your header, should fix some of the ie bugs.
IE has problems with the :hover pseudo-class on anything other than anchor elements so you need to change the element the hover is affecting to the anchor itself. So, if you added a class like "image" to your anchor and altered your markup to something like this:
<div class="myImage"><img .../></div>
You could then alter your CSS to look like this:
.myImage a.image
{
border: 1px solid grey;
padding: 3px;
}
.myImage a.image:hover
{
border: 3px solid blue;
padding: 1px;
}
Which should mimic the desired effect by placing the border on the anchor instead of the image. Just as a note, you may need something like the following in your CSS to eliminate the image's default border:
.myImage a img {
border: none;
}

Resources