Automatically Combining / Merging CSS Selectors with Preprocessors - css

A basic CSS example. Every browser I have come across will render the item with the margin & padding and a red border
.test{
margin: 4px;
border: 1px solid black;
padding: 4px;
}
.test{
border: 1px solid red;
}
Naturally if I was writing this CSS by hand I would replace the black with red and only have one rule.
But If the first rule comes from a parent CSS file (or in my case a LESS file) that I can't edit because it is used elsewhere, or is from a 3rd party library that I don't want to hack then I see no alternative but to add an extra rule.
Now since I am using server side LESS -> CSS compilation with minification, it seems perfectly reasonable to me that the compressor/minifier should reduce the rules down to just
.test{
margin: 4px;
border: 1px solid red;
padding: 4px;
}
But everything I have tried, keeps both rules; some of the compressor/minifiers go as far as removing newlines
.test{margin:4px;border:1px solid black;padding:4px}.test{border:1px solid red}
It strips out a single newline character but left an entirely unnecessary rule declaration in. This seems bizarre to me.
Is there any system than can do this? (preferably an add on for node.js) If not, do we know why not? Seems like quite a big file size saving with no downside to me.
disclaimer I have tried searching for combining selectors, merging selectors and few variations, apologies if I have missed the common term for this procedure, seems likely since the gains just seem so obvious I have to be missing something!

Why It Cannot and Should Not Be Done
You state:
Every browser I have come across will render the
item with the margin & padding and a red border.
That is because, of course, the cascading nature of CSS. It is designed to work like that for the express purpose of overriding. Which is exactly the point of why (and how) you "add an extra rule" in your CSS to override.
There is a Reason
Now, I can see your point in a preprocessor perhaps "merging" code with the same selector for minimization purposes. However, (1) there would be a rare (if ever) case where the two classes would actually follow one right after the other in the CSS code, as your example shows (and in such a case, minimization would be okay). Usually there is going to be intervening CSS that can affect how the cascade might play out in rendering. Which leads to (2), it would require more logic than is initially obvious (or even possible) to implement. Consider this example:
HTML
<div class="test1 test2"></div>
CSS (Framework File)
.test1 {
margin: 4px;
border: 1px solid black;
padding: 4px;
}
.test2 {
border: 1px solid blue;
}
CSS (Developer File)
.test1 {
border: 1px solid red;
}
The above code if output as normal should render a red border by the cascade, just as the developer wants. Now suppose LESS or another preprocessor does minify it as you desire. It could end up like this:
Theoretical Minimization
.test1 {
margin: 4px;
border: 1px solid red;
padding: 4px;
}
.test2 {
border: 1px solid blue;
}
And would in fact render as blue not as red! This is because the two .test1 merged, now making the .test2 last in the cascade order rather than the second instance of .test1 being last. So a preprocessor would have to be "smart" enough to figure out a theoretically infinite number of possible cascade combinations, and that without knowing what the html coding is that ultimately influences the decision (like here, where the html double classes in conjunction with the cascade order is what is determining the final rendering).
Had the preprocessor merged into the second instance, that does not solve the problem, as what if developer had put a second instance of .test2 after the second instance of .test1, but did not define a different border color? The .test2 border color would still have overridden by merging with the following .test2.
This illustration should show why such a minimization cannot and should not be done--the interactive logic between possible html form and CSS cascade is impossible to predict what or how to merge except in a case were two exact selector strings in the CSS immediately followed one another. Any other case could make a wrong decision.

Related

Changing checkbox layout without using label

Is it possible to change the layout of a checkbox without adding the label tag in CSS?
Things like this do not have any effect:
input[type=checkbox][disabled] {
background-color: green;
border: 10px solid red;
}
The only thing I found so far is how to change the opacity.
I'm not sure if this will be much use to you, but it does allow you to "style up" a checkbox without the need for a label. I've remove the disabled flag so you can swap between the different styles. Shouldn't be difficult to add it back in if this will work for you.
Fiddle is here.
input[type=checkbox]:checked:before {
background-color: green;
border: 10px solid red;
}
input[type=checkbox]:before {
content:'';
display:block;
height:100%;
width:100%;
border: 10px solid green;
background-color: red;
}
The above only works on Chrome, however, it seems like Chrome is in the wrong where the specification is concerned.
A fuller answer here: CSS content generation before or after 'input' elements
As of today there is no solution, if we assume a cross browser functional styling, to style the <input type="checkbox" > alone, other than a few properties like opacity, width, height, outline (and maybe a few more).
Using a label (or other content elements) is what you need to do that and here is a good (which this question is likely a duplicate of) post with lots of options: How to style checkbox using CSS?
Note: If you know more properties, feel free to update this answer.

Conflicting CSS Classes with same precedence (design principle)

I'm re-evaluating the effectiveness of my CSS design choices after reading about SMACSS.
One of the conflicts I've examined is:
<button class="cool-text button"></button>
Semantics aside, the object in question has two classes which do not extend each other in anyway. Now, if the CSS were:
.cool-text {
background-color: black; // want this
color: green; // don't want this
font-size: 16px;
text-shadow: 0 1px 0 yellow;
}
.button {
background-color: white; // don't want this
border: 1px solid;
border-radius: 4px;
color: #eee; // want this
}
Once again, this is not an ideal example. I was wondering, what if I wanted the background-color from .cool-text and the color from .button. In a programming language, an object can have two classes, and you can specify how to resolve conflicts in method names. I guess similarly, I could specify .cool-text.button, but I would have to re-write the properties, which seems very bad.
.cool-text.button {
background-color: black;
color: #eee;
}
Are there any workarounds using SCSS?
Also, is it a bad idea to rely on the positions of the classes within the class attribute (in vanilla CSS). Classes that are specified first have higher priority, for instance:
<button class="green-button button"></button>
In this example, .green-button has higher precedence.
This seems to add CSS specificity to HTML. What if there were lots of classes, you would have to spend time figuring out which ones should go first and that seems very counter-intuitive.
Per Quentin, it's determined by the order within CSS.
It all depends on the rule specificity and order.
Your solution makes perfect sense to me, because your original idea is not ideal (taking x from class1 and y from class2, yet the classes are parallel). However, if you end up writing too many of those exception rules, like:
.cool-text.button {
background-color: black;
color: #eee;
}
it means something's not quite right with your design. Why simply not design a cool-button class then? If your .button is meant to be one of the base classes, put it on the top of the CSS file, let the other (more specific) classes override it easily.
Also, please refrain from using !important unless absolutely necessary.
See this nice specificity calculator: http://specificity.keegan.st/

Duplicate background colors in bootstrap's css

I have found the following css declaration in twitter bootstrap (link and source). Basically it declares the following:
background-color: #eee;
background-color: rgba(86,61,124,.15);
border: 1px solid #ddd;
border: 1px solid rgba(86,61,124,.2);
As far as you see - there is a duplicated background color and border. If it would be anywhere else, I would ignore it thinking 'these guys just do not know css'.
But because this is highly used open-source project, done by professionals, I have a pending question: is it really a bug or does it make sense (if so can someone explain to me why someone would use it?).
rgba() color value has been introduced in CSS level 3 specification.
It declares colors in Red-green-blue model including alpha, allowing specification of the opacity of colors.
rgba() is not supported in old web browsers such as IE8, Opera9, ... Thus, developers use a solid color as a fallback.
In this particular instance, the primary declarations treat as fallback for the next ones:
background-color: #eee; /* The Fallback */
background-color: rgba(86,61,124,.15);
border: 1px solid #ddd; /* The Fallback */
border: 1px solid rgba(86,61,124,.2);
If a web browser supports rgba() the second declaration will override the first one. But if the web browser doesn't understand rgba() color, the second declaration will be ignored, Thus the first one will be appled to the element(s).
However there are some alternatives you might want to consider:
Bulletproof, cross-browser RGBA backgrounds, today
CSS Transparency Settings for All Browsers

Make two Joomla modules appear as one with a single outlined border?

I have two Joomla module positions. They are stacked in the same module position. I need for these two modules to appear on the web page as a single displayed module with a single border surround all of it.
How can this best be accomplished without modifying PHP code for either of these modules? I'm thinking this might be done with CSS, but I'm not an expert with CSS. Maybe a Module Class Suffix added for both of these modules could make them appear appear seamlessly joined? If so, how do I do this?
OKay, without being able to see the HTML, I'll pretend the two components get outputted as <div>s with the class themodule, and that some padding, borders and margins have been applied something like this:
.themodule {
padding: 1em;
border: 0.1em solid black;
border-right: 0;
margin: 2em;
}
If you add this:
.themodule + .themodule {
padding-left: 0;
border-left: 0;
border-right: 0.1em solid black;
margin-left: 0;
}
That means any .themodule directy after another one will get the left padding, border and margin chopped so it butts right up against the previous one and visually is part of the same box.
Hopefully you can apply to your case, but let me know if you have questions.

CSS property - set global border first, and then specify border-bottom?

What is the best CSS practice to achieve a border on all sides of a container, apart from, for example, the bottom?
The border property cannot specify different values for each side.
Option 1: Overwriting Rules
border: 1px solid red;
border-bottom: none;
Seems that an extra computation is needed — similar drawbacks as CSS resets (at least philosophically).
Option 2: Setting Specific Rules
border-top: 1px solid red;
border-left: 1px solid red;
border-right: 1px solid red;
Might be more correct (in terms of CSS "semantics")
But if you want to change the border specifics, then it'll require
multiple changes (harder to manage).
Actually it totally depends on you, what is more convenient to you, it also depends on some state like if I want the color of all borders to be same I'll go for 1st but If I think I need to change the colors of each side of the border in near future I'll go with the second 1, but for now, I'll stick to first option
Reasons:
Less CSS to be stated
Specifically it shows that I want border-bottom as none
As you said I don't need to change each and every property: value if I need any changes
If you say proper semantics, proper semantics define very specifically like
border-color: /*Whatever*/;
border-width: /*Whatever*/;
border-style: /*Whatever*/;
Now am sure you don't want to be this specific
If you only want to specify the values once, you can specify the color and width for all, then the style specifically for the sides:
border-color: red;
border-width: 1px;
border-style: solid solid none solid;

Resources