CSS selector to invert selection - css

Is there any advantage or disadvantage in using :not() over an inverted selector logic? May it be in performance, safety or browser support, which approach is recommended?
Either:
.imageSlider img:not(:first-child) {
display: none;
}
Or:
.imageSlider img {
display: none;
}
.imageSlider img:first-child {
display: block;
}

Sometimes it's could be better to use :not.
<p class="my-paragraph">
<div class="something"></div>
<div class="something-else"></div>
<div class="an-other-thing"></div>
<div class="an-other-thing"></div>
<div class="last-one"></div>
</p>
In this case, if you want to hide everything except div .an-other-thing it will be quicker to write :
.my-paragraph div:not(.an-other-thing) {
display: none;
}
Instead of:
.my-paragraph div {
display: none;
}
.my-paragraph div.an-other-thing {
display: block;
}
In most of cases, a longer CSS means longer time to execute it

As of January 2017, the :not selector is currently only supported by Safari browsers with a mere 11% global browser support. I would stay away from using it in production code.

Related

css class override not working for just one specific class

In my Wordpress CSS I have added a few extra classes. Depending on screen widht I want to override these. This works fine, except for one class. I am at the end of my wits what could be the cause. Here's the code excerpt (class "field-space" is being successfully overriden, class "formflex" is not)
.formflex {
display: flex;
background-color:yellow;
}
.field-space {
padding-right: 20px;
background-color:lightgrey
}
#media only screen and (max-width: 767px) {
    .formflex {
       ! flex-direction : column;
background-color:blue;
    }
.field-space {
padding-right: 60px;
background-color:green;
}
}
The background-color specification is there for testing whether things work. The color of elements with a field-space dev are changing, the ones for formflex are not. Am I missing some typo (checked a thousand times)?
Tested with Firefox and Chrome.
https://developer.mozilla.org/en-US/docs/Web/CSS/important
A ! delimiter followed by the important keyword marks the declaration
as important. The !important flag alters the rules selecting
declarations inside the cascade. A declaration that is not important
is called normal.
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
Specificity is the algorithm used by browsers to determine the CSS
declaration that is the most relevant to an element, which in turn,
determines the property value to apply to the element. The specificity
algorithm calculates the weight of a CSS selector to determine which
rule from competing CSS declarations gets applied to an element.
Just to make it clear because your words showed some confusion, you are overriding the specificity of a single css attribute and not the whole class. Those are ruleset applied to elements responding to a given selector. By the way you were doing it wrong...
...and since here you don't need to override any specificity, the !important clause is not needed.
As a side note, .field-space element needs the height set when displayed vertically.
.formflex {
display: flex;
background-color: yellow;
}
.field-space {
padding-right: 20px;
background-color: lightgrey
}
#media only screen and (max-width: 767px) {
.formflex {
flex-direction: column;
background-color: blue;
}
.field-space {
padding-right: 60px;
background-color: green;
line-height: 1em;
height: 1em;
}
}
.formflex > *:not(.field-space){
border: solid 1px gray;
}
<div class="formflex">
<div>Item</div>
<div>Item</div>
<div>Item</div>
<div>Item</div>
<div class="field-space"></div>
<div>Item</div>
<div>Item</div>
<div>Item</div>
<div>Item</div>
</div>

How can I combine the same CSS properties for different elements?

I have two elements: tooltip and tooltip-line.
There is common properties for each elements:
[tooltip]::after, [tooltip-line]::after {
position: absolute;
opacity: 0;
visibility: hidden;
/* Other common properties */
}
Next, I have different properties for each element.
[tooltip-line]::after { /* One line tooltip */
content: attr(tooltip-line);
white-space: nowrap;
}
[tooltip]::after { /* Multiline tooltip */
content: attr(tooltip);
width: 200px;
white-space: normal;
}
Is this a correct usage? Including similar classes. Or should I copy all properties to each declaration block?
Here's a different approach which might be slightly more scalable. Using CSS custom variables, we can override any default class values by resetting them in the multiline class. Finally, I would make the attributes containing the tooltip content identical—and valid data attributes—if possible.
.tooltip::after {
--tooltip-white-space: nowrap;
content: attr(data-tooltip-content);
white-space: var(--tooltip-white-space);
}
.tooltip.multiline::after {
--tooltip-white-space: normal;
}
.container {
width: 250px;
border: 1px solid red;
}
<div class="container">
<div class="tooltip" data-tooltip-content="my tooltip content should not wrap no matter what"></div>
<div class="tooltip multiline" data-tooltip-content="my multliline tooltip content should wrap"></div>
</div>
jsFiddle
It's absolutely right to divide the css in multiple blocks.
One of the first thing to know while writing code in any language is NOT to repeat yourself.

Using :target and adjacent sibling selectors to make a toggle botton

Anyway, I'm trying to create a toggle link, which is basically two buttons on top of each other. One of them would become display:none when it is clicked, and vice-versa.
Currently, my CSS is like this
#main-nav:target + .page-wrap {
position:absolute;
left:-80px;
#open-menu {
display: none;
}
#close-menu {
display: block;
}
}
...but the #open-menu and #close-menu display options don't seem to be showing. Any help?
EDIT:
Alright so I need a preprocessor okay ._.
EDIT AGAIN:
Got it working, thanks guys! Just wondering, is there a way for my entire page div (excluding the menu) to slide out of the page? Or is it some simple overflow-x:hidden?
If you're not using a preprocessor and you don't want to, I suspect you can rewrite your CSS like this, assuming your HTML structure actually corresponds to the selectors:
#main-nav:target + .page-wrap {
position: absolute;
left: -80px;
}
#main-nav:target + .page-wrap #open-menu {
display: none;
}
#main-nav:target + .page-wrap #close-menu {
display: block;
}
Of course, if #open-menu and #close-menu aren't descendants of .page-wrap, then this won't work at all, even if you do use a preprocessor to support writing nested style rules (as a preprocessor can't do something if it cannot already be done with plain CSS).
As mentioned, if these elements aren't related in a way that can be expressed with descendant and sibling combinators, you'll have to make use of JavaScript to achieve what you're trying to do.
As a demonstration, I tried the following:
<div class="page-wrap">
<a id="close-menu" href="#open-menu">Close</a>
<a id="open-menu" href="#close-menu">Open</a>
</div>
with the following CSS:
.page-wrap #open-menu {
display: block;
}
.page-wrap #close-menu {
display: none;
}
.page-wrap #open-menu:target {
display: block;
}
.page-wrap #open-menu:target + #close-menu {
display: none;
}
.page-wrap #close-menu:target {
display: block;
}
.page-wrap #close-menu:target + #open-menu {
display: none;
}
Fiddle Reference: http://jsfiddle.net/audetwebdesign/5aSdW/
Demo Link: http://jsfiddle.net/audetwebdesign/5aSdW/show
Every time you click the Open or Close link, the alternate link is displayed.
I am not sure if this is overly useful, but it can be done.

Can I adjust the width of a <pre> area to fit the text?

I have the following:
<p>This is a test</p>
<pre>public class Car {
protected Car() { }
protected Car(int speed) { }
protected void Car() { }
}</pre>
<p>Another line</p>
and
pre {
font-family: monaco,consolas,"courier new",monospace;
font-size: 1em;
min-height: 3em;
overflow: auto;
padding: 1em;
xwidth: 80%;
background-color: red;
}
When the text displays the <pre> background goes the full width of the page. I have a demo here:
fiddle
What I would like is for the red background to stop just after the far most right character of my code. I don't want to see a big red area that extends from one side of the page to another.
Can someone tell me if it is possible to do this with CSS. I really am not sure as I cannot think what I can do.
Thanks
You can use display: inline-block;:
http://jsfiddle.net/hLVV9/1/
Although please check out the browser support, because it wouldn't surprise me if IE doesn't support it.
The best solution so far :
pre {
white-space: pre-wrap;
}
You can use float:left and a clearing div to achieve this.
http://jsfiddle.net/hLVV9/2/
For that behavior you will need to float your <pre>. Floated blocks of course cause some layout changes, so you need to wrap it in another clearing block element:
<div class="pre-wrapper"><pre>Lorem ipsum</pre></div>
.pre-wrapper {
overflow: hidden;
}
.pre-wrapper pre {
float: left;
}
Adding display: inline-block should do it for FF, Safari and Chrome.
But make sure to check in all browsers and how it behaves, specially IE
One more approach:
pre {
display: table;
border-collapse: separate;
}
It allows the margins to natively collapse (in contrast to display: inline-block). As a bonus, it works with a wide range of browsers starting with IE8 or even older.

How to show images/links on DIV hover?

How can I achieve the affect like here on SO when you hover over a comment:
an arrow up to vote up
a flag to mark that message
if you are the comment author you get option to delete as well
How can I make links and images like that show when hovering over a DIV or even a table cell?
Try this:
.comment .button {
visibility: hidden;
}
.comment:hover .button {
visibility: visible;
}
Assuming your HTML is something like this:
<div class="comment">
<a ...><img class="vote button" ...></a>
<a ...><img class="flag button" ...></a>
<a ...><img class="delete button" ...></a>
<span class="comment-text">...</span>
</div>
Andrew noted that this pure CSS solution won't work in IE6. And as Noel pointed out, hovering just isn't an option in mobile browsers. You can use progressive enhancement to have the buttons always visible in those cases.
<style type="text/css" media="screen">
.comment .button {
visibility: hidden;
}
.comment:hover .button {
visibility: visible;
}
</style>
<!--[if lt IE 7]>
<style type="text/css">
.comment .button {
visibility: visible;
}
</style>
<![endif]-->
IE6 will understand the first style, making the buttons hidden, but not the second, making them visible again on hover. The third style is in a conditional comment, which non-IE browsers and IE7+ will ignore. It overrides the first style, making the buttons visible always.
div:hover {
background-image:url('arrow.gif');
}
The key to what you are trying to do -- as I think the other answers are saying-- isn't to create the content on hover, but to make it "visible" on hover. It's always there, just not in a way the user can see or interact with. So you'd have something like:
<div class="vote_arrow">
<a ...>Clicking on me is fun</a>
</div>
and then a CSS rule like:
.vote_arrow a {
display:none;
}
.vote_arrow:hover a {
display: block;
}
Be aware, though, that this method requires that the user have CSS turned on. Make your hidden content set up in such a way that if I have CSS off, the links still make some amount of sense.
Consider the following HTML:
<div class="special">
<div class="links_holder">
<a class="flag" title="Flag" href="flag.html">Flag</a>
</div>
<div class="content">
Hello, this is my content!
</div>
</div>
You can use the following CSS to hide the links:
div.special div.links_holder {
float: left;
width: 16px; /* For a 16x16 link image */
margin: 0 4px 0 0; padding: 0;
visibility: hidden;
}
div.links_holder a.flag {
display: block;
width: 16px; height: 16px;
overflow: hidden;
/* Move the text out of the way
It's there for screen readers */
text-indent: -9999px;
background: url('flag.gif') top left no-repeat;
}
div.special:hover div.links_holder {
visibility: visible;
}
Note that this will not work in IE6 since IE6 and below only supports the :hover pseudo-tag on <a> tags. In which case you'll need to revert back to a JavaScript solution. Example with MooTools:
$$('div.links_holder a.flag').each(function(el) {
el.addEvents({
'mouseenter': function() {
el.addClass('hover');
},
'mouseleave': function() {
el.removeClass('hover');
}
});
}, this);

Resources