How to merge multiple CSS rules from duplicated selectors? - css

Precursor:
Under normal circumstances, I would never do this.
I have a CSS file that I am currently collaborating on with another person. I built the file initially, then they have added rules to it after the fact. But, instead of adding rules to selectors that already exist, they have duplicated selectors everywhere. I don't even want to get into how disorganized the file has become. The problem is that the duplicated selectors are spread out all over the file now and it could take some time to sort it out.
Anyway, I am currently in the process of trying to clean up the file. I have tried beautify, css format, etc in my editor (ST3), which cleans up fine but still leaves the duplicate selectors. I have tried various online tools like CSS Lint, ProCSSor, Dirty Markup, CleanCSS and so far none of these tools give me the desired result.
Is there any way that these selectors can be merged by some other means instead of manually?
Here's an example of my situation, just for reference:
I'd like to turn this...
.sameClass {
float: left;
width: 100%;
margin: 0;
padding: 0;
}
.differentClass {
border: none;
background: black;
padding: 0;
}
.sameClass {
font-weight: bold;
font-size: 24px;
display: inline-block;
}
into this...
.sameClass {
float: left;
width: 100%;
margin: 0;
padding: 0;
font-weight: bold;
font-size: 24px;
display: inline-block;
}
.differentClass {
border: none;
background: black;
padding: 0;
}

CSSO (Github project) is the tool will help you merge identical CSS classes.
It can be configured to execute some cleaning, compaction and restructuring.
Test in sandbox here : https://css.github.io/csso/csso.html
// Input
.card {box-shadow: none;}
.foo { color: #ff0000; }
.bar { color: rgba(255, 0, 0, 1); }
.card {border: 1px solid grey;}
// Output compacted + merged
.bar,.foo{color:red}
.card {box-shadow: none;border: 1px solid grey;}

A simplistic approach would be to sort your CSS file(s) by selector. This can be done by considering each rule as a "paragraph" (meaning you will have to ensure there are empty lines between rules, and nowhere else), and then using your editor's "sort paragraph" feature, if it has one. For instance, emacs has the M-x sort-paragraphs command.
Once multiple rules for the same selector are grouped together, you can manually go in and combine them.

Related

Unable to get CSS variables to work in any browser

I am having trouble getting CSS variables to work, I am doing the following:
:root {
--base: #ffcd600;
--spacing: 10px;
--blur: 10px;
}
img {
padding: var(--spacing);
background: var(--base);
}
However I am seeing the element inspector as shown below:
img {
padding: var(--spacing);
background: var(--base);
}
--base: #ffcd600;
too many characters in your hexadecimal value.
A little confused as to what you're asking. But when using the provided code I did not encounter any issues, with one exception. As Obsidian has stated your Hex has one extra value. Removing the extra 0 will work.
If you were to test it like so, what do you see?
:root {
--base: #ffcd60;
--spacing: 10px;
}
h1 {
color: var(--base);
padding: var(--spacing);
}
If this also does not display correctly then have you tried clearing your cache?

Not able to extend Less mixin

I would like to have below CSS output using Less
.selected-values,
.selected-values a {
background-color: #505050;
color: #fff;
}
.selected-values {
display: block;
}
.selected-values a {
text-decoration: none;
}
So far i have thought of below Less syntax, but it is not working.
.selected-dropdown-values() {
background-color: #505050;
color: #fff;
}
.selected-values:extend(.selected-dropdown-values) {
display: block;
}
.selected-values a:extend(.selected-dropdown-values) {
text-decoration: none;
}
I am not able to apply any extend logic to generate this syntax. I might be missing something or i am unaware about how to do it properly in Less. Also, I do not want .selected-dropdown-values mixin to output in CSS.
As mentioned in comments and discussed in the chat, Less currently does not support extending of mixins (there is a request and it might get addressed in v2.0.0 or later). (Note: To be more precise with wordings, extending of mixins which are not output in CSS is not supported.)
So, the best way forward would be to do the below:
Less:
.selected-dropdown-values { // just remove the braces
background-color: #505050;
color: #fff;
}
Just remove the braces from the .selected-dropdown-values rule. Ofcourse this would cause that rule also to be present in the CSS output but given that we are using extend, it would mean only one extra line in CSS output.
Output:
.selected-dropdown-values,
.selected-values,
.selected-values a {
background-color: #505050;
color: #fff;
}

How can I simplify this SASS statement?

How can I simplify this SASS so that I only write .question-sector-answer the once? I need to apply different styles to the .question-sector-answer if the parent div has a class of both .question-row and .question-review. This currently seems unwieldy and I'm sure could be simplified and made more elegant:
.question-row {
border-bottom: 1px solid #ddd;
&.question-review {
.question-sector-answer {
padding-top: 30px;
}
}
.question-sector-answer {
padding: 15px;
}
}
I don't see how you can simplify it. You need to use 2 different styles for .question-sector-answer under different parents. Since it's impossible in css to access parent selector, you have no choice but do what you did (well, in SASS you kind of can - see below). Although my personal preference to always put more generic selectors on top and more specific ones to the bottom like so:
.question-row {
border-bottom: 1px solid #ddd;
.question-sector-answer {
padding: 15px;
}
&.question-review {
.question-sector-answer {
padding-top: 30px;
}
}
}
So in SASS you can access parent selector with & using it in certain way, but I don't think you can recreate your styles with it, the best I could come up with was this but it looks uglier than your original way of doing it, but you're welcome to play with it:
.question-row {
border-bottom: 1px solid #ddd;
}
.question-sector-answer
{
.question-row & {
padding-top: 15px;
}
.question-row.question-review &
{
padding: 30px;
}
}
You can read more about accessing parent selectors with & here
.question-row {
border-bottom: 1px solid #ddd;
}
.question-sector-answer {
padding: 15px;
.question-review & {
padding-top: 30px;
}
}
De-nesting here does two things: (1) creates terser, more flexible CSS and (2) allows the parent & selector. To compensate for the decrease in OOP, we slightly indent to imply subjugation. But in SASS you want to avoid the temptation to nest when not totally necessary, because nesting for OOP's sake tends to create more problems than it solves.

LESS CSS - Change variable value for theme colors depending on body class

Getting to grips with LESS here but one thing is still a little unclear.
Lets say I have multiple color themes for my website, controlled by a class on the body tag. From this I can redefine the various colors for each element within each theme. Easy enough but fairly time consuming if I have a lot of elements to change... and a lot of themes. Every time I add a new theme I need to write out all the selectors again, with different color values.
I am basing my working so far on another post I found:
LESS.css variable depending on class
... However it still seems overly complicated for what I want to do in that I still have to write out all the selectors and include the mixin before dropping in the same CSS with the color variable.
I have created a CODEPEN HERE
I'd appreciate it if anyone had time to take a little look and advise me how I could approach this differently or how I could streamline this process.
Many thanks to anyone who helps out :)
Assuming you remain with wanting to theme it within one style sheet (and not multiple sheets as cimmanon noted in the comments), and assuming you are using LESS 1.3.2+, then the following code works to reduce the amount of duplication by setting up a loop through the classes that need theme changes.
Note that this does not work on Codepen (it is throwing an error uncaught throw #, perhaps because they are running an earlier version of LESS), but you can see it compiling correctly by putting the code into LESS's compiler.
LESS (based off your Codepen code with an added theme for demo)
//////////////////////////////////////////////////////
// CONSTANTS
#lightColour: #fff;
#darkColour: #000;
#lightBg: #fff;
#darkBg: #000;
#numberOfThemes: 3; //controls theme loop
//////////////////////////////////////////////////////
// MIXINS
//Theme Definitions by parametric mixin numbers (1), (2), etc.
.themeDefs(1) {
#lightColour: #f00;
#darkColour: #fff;
#lightBg: #f00;
#darkBg: #fff;
}
.themeDefs(2) {
//inverse of 1
#lightColour: #fff;
#darkColour: #f00;
#lightBg: #fff;
#darkBg: #f00;
}
.themeDefs(3) {
#lightColour: #cfc;
#darkColour: #363;
#lightBg: #cfc;
#darkBg: #363;
}
.curvy {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
//////////////////////////////////////////////////////
// GENERAL STYLING
* {padding: 0;margin: 0;}
html {text-align: center;}
h2 {padding: 20px 0;}
.box {
.curvy;
color: #lightColour;
background: #darkBg;
display:inline-block; width:10%; padding:20px 5%; margin:0 1% 20px 1%;
}
//////////////////////////////////////////////////////
// THEME BUILDING
.buildThemes(#index) when (#index < #numberOfThemes + 1) {
.theme-#{index} {
.themeDefs(#index);
color: #lightColour;
background: #darkBg;
.box {
color: #darkColour;
background: #lightBg;
}
}
.buildThemes(#index + 1);
}
//stop loop
.buildThemes(#index) {}
//start theme building loop
.buildThemes(1);
CSS Output (only showing the looped theme css for brevity)
.theme-1 {
color: #ff0000;
background: #ffffff;
}
.theme-1 .box {
color: #ffffff;
background: #ff0000;
}
.theme-2 {
color: #ffffff;
background: #ff0000;
}
.theme-2 .box {
color: #ff0000;
background: #ffffff;
}
.theme-3 {
color: #ccffcc;
background: #336633;
}
.theme-3 .box {
color: #336633;
background: #ccffcc;
}

Proper use of 'Mixins' in LESS

I am trying to create simple 'templates' using less but I imagine I might be doing so incorrectly..
here is what I am going for:
<div class='box'>content</div>
and the .less file:
//this is the mixin
.blueBoxNotificationDiv {
text-decoration: none !important;
position: absolute;
background: #EBEBEB;
width: 100%;
border-top: 1px solid #999;
bottom: 0;
height: 21px;
}
now let's say I want to apply this 'mixin' to the div '.box'.
this is how I would have it written in the .less:
.box {
.blueBoxNotificationDiv;
}
What is the correct way to go about this?
LESS variables if not written out properly (including the rule) will prevent anything else from being read in your less file.
Example of the problem:
#color1: #000000;
#color2: #ffffff;
#color3: ##e6e6e6;
.container {
color:#color1;
}
.....etc
This should be pretty obvious but small errors can be easy to miss.. the variable '#color3' has two hashs '##'. This will break the less EVEN if you do not call the variable and none of the following code will be read (near as I can tell). Problem solved!

Resources