prevent styles from applying by cascade when using LESS nested rules - html

We're developing a large plugin based front-end system and trying to figure out how to compose CSS rules. Basically there are two ways:
Specify parents in the class name
Specify parents in the selector (by using LESS nested rules)
And the corresponding HTML:
<div class="dashboard">
<span class="dashboard__title"></span>
<div class="custom-widget">
<span class="dashboard__custom-widget__title"></span>
</div>
</div>
And for second approach:
<div class="dashboard">
<span class="title"></span>
<div class="custom-widget">
<span class="title"></span>
</div>
</div>
I want to specify specific style for .title inside .dashboard, so using the first approach CSS will look like that:
.dashboard__title {
//styles here
}
With the second approach CSS will look like this:
.dashboard .title {
//styles here
}
which takes advantage of LESS nesting capabilities:
.dashboard {
.title {
//styles here
}
}
We really like the second approach as it makes LESS stylesheets easy to read by collapsing rules specific to any particular element and it also allows for short style names. However, it has a problem, which is cascading - in the case at hand styles defined for .title inside .dashboard will also be applied for .title inside .custom-widget. If we use the first approach the doesn't happen.
Please advice on ways to use LESS nesting capabilities but avoid the problem described.
EDIT:
It seems that I've found a solution which combines two approaches:
.custom-widget {
&__save-icon {
&--active {
padding: 777px;
background-image : url('');
}
}
}
Produces this kind of class:
.custom-widget__save-icon--active

Just choose your element by selector like below:
This style affects only for immediate children of a .dashboard element which have class .title.
.dashboard > .title {
//styles here
}

I think the question is a bit ambiguous because there is no »do it that way« answer possible. BUT some reasoning will hopefully give some hints. I think the first question you should pose yourself is: will a span.title happen to appear in other places too, so that the style rules for it can be reused.
In this case you could start out by abstracting the style definitions like that:
html:
<div class="plugin dashboard">
<span class="title">Hey There!</span>
</div>
scss:
//general rules for each title in each plugin
div.plugin {
span.title {
}
}
//override or specify
div.dashboard {
span.title {
}
}
This way, by adding a second class you can take advantage of cascading nature of CSS and with tools like LESS or SASS you can guarantee that the order of style rules will be preserved.
Otherwise, if you just want to make sure that your style rules only apply for elements inside the .plugin__container, just scope it as you did in the question and take care that the outermost »main entry point« is unique enough.
div.plugin-namespace {
//all your rules here…
}
I hope It helped! Good Luck!

Related

Is it a bad practice to use custom HTML attributes and style them with CSS?

Is there any problem creating a CSS class like this:
[test] { font: 13px; }
and use it in an HTML attribute as this:
<div test></div>
Would the performance in some browsers be affected by using this method?, I've tested it with Mozilla Firefox and Google Chrome and they seem to work with no problems.
Your custom attributes are not valid HTML. You must use data-* attributes if you want to put custom data on your elements. This makes what you are doing bad practice.
In addition, there are CSS classes already that should meet your needs, unless there is more to your question than you have described.
While there is no problem in applying styles this way, and sure it does work in the browsers, you have to understand that this is not a standard way of applying styles.
Since you have also asked from a 'practice' perspective, then, yes, this surely is not the right practice. The idea is: HTML is used to define the elements to be shown within the browser window, CSS is used to apply any styling that needs to be applied on these elements and JavaScript is used to perform any 'action' on it. So, from a practice perspective, this surely is bad practice!
On another note, why the reluctance to create a class and apply it on the div? After all, this class can be reused as and when required. If you need it only once, then why not create an id selector?
HTML:
<div class="rightApproach">The right way of applying styles</div>
CSS:
.rightApproach { color:Red; }
See this fiddle where you can see your approach as well as the correct way of applying styles, be it class selector or id selector.
http://jsfiddle.net/JkRPt/
It's better to use classes. This way will not work in older browsers and it's not professional.
However it doesn't have any performance issues.
HTML:
<div class="test">
CSS:
.test { font:13px; }
its good to use classes. Example:
<div class="module accordion expand"></div>
/* All these match that */
.module { }
.accordion { }
.expand { }

How to reuse css class content in another class without copying?

Is it possible to use existing css class as content in another class ?
I mean something like:
/* Contained in some library: */
.class1 { text-indent: 100 }
/* I can not change this: */
<span class="class2">
The definition for class2 is also contained in another library. So I can not change it directly.
/* But I want to do something like that in my CSS file: */
.class2 { .class1 }
I know it is not possible in that form. But maybe one can use some trick to achieve the behaviour without copying of the content of class1? I need this because I want to redefine class with content from another CSS class. Our project uses jQuery as well, but I would do it rather with CSS.
EDIT: I should explain more, I could not change how .class1 is defined, because this class is in a library, and I could not change mark up on span class.
It is imposible to do in standard CSS what you are commenting, as there is not pure inheritance.
Despite it doesn't apply with your code restrictions, this is the closer way to do it:
.class1, .class2 { text-indent: 100 }
.class2 {
/* Styles you want to have only in class 2 */
}
<span class="class2" />
On the other hand, as #A. Wolff has pointed out, you can still use js/jq to add class to specific elements: $(function(){$('.class2').addClass('class1')}); Then just set a specifc CSS rule for these elements.
In case you don't want to use JS, for something like that you'd need to use SASS or similar, which "compiles" to CSS.
CSS has no means to reference one rule-set from another.
Your options include:
Using multiple selectors for things with common rules
.menu,
.nav {
font-weight: bold;
}
.nav {
display: inline-block;
}
Using multiple classes on a single element
.menu {
font-weight: bold;
}
.nav {
display: inline-block;
}
<li class="menu nav">
Generating your CSS programatically
For example, with SASS
#mixin menu {
font-weight: bold;
}
.nav {
display: inline-block;
#include menu;
}
Yes, it is possoble.
Write:
.class1,.class2 {text-indent:100;}
.class1{color:red;}
.class2{font-size:30px;}
More info here.
Another option is to use LESS to do this. It's a very good tool and do some improvements to your CSS development.
Take a look at theirs documentation, it's very nice. About the compilers, I use Koala and recommend it.
You mentioned in one comment that you cannot use LESS, but I think perhaps you misunderstand how LESS (or another preprocessor) could help you. That is, you have not given any reason that I can see why you cannot use it (even in your update). As I understand your problem, you have the following parameters:
Cannot change html
Cannot change the css file that defines .class1.
You can change the css file that defines .class2.
If the above is correct, then here is how you use LESS (version 1.5+). You make your file defining .class2 a .less file. Then, to keep it clean, I believe you are going to have to do a two step process (it may be you can do step 2 without step 1).
Step One: Make the CSS into LESS
Create a file, let's say CSStoLESS.less and put this in it:
#import (less) /path/to/your/your-css-defining-class1.css;
This will import the css and make the processor consider it as LESS code. It is possible that the next step does that as well, I have not had opportunity to test it out.
Step Two: Use that file as reference in your LESS
By doing this in your .less file defining .class2:
#import (reference) /path/to/your/CSStoLESS.less;
.class2 { .class1; }
You are importing the previous css file that has been converted to less as reference only. This prevents you from getting duplicate selectors for .class1 or anything else contained in your original css file. Now you can use an inclusion of .class1 just like you show in your question to make the properties of .class1 become that of .class2.
It may be that this alone works:
#import (reference) /path/to/your/your-css-defining-class1.css;
.class2 { .class1; }
What I don't know is if the (reference) inclusion also defaults to making .css into LESS code like the (less) inclusion typecasting does in step one. I need to research this out more. If so, then it is a one-step, not a two-step process.
The best way would be to redeclare class1 just below your custom css ends and override it with the values that you are looking for. This way, the inherited values, that you cannot change + the values that you need to incorporate, both shall apply.
I am assuming you want whatever is in .class1 plus some extra properties in .class2
One way is to simply apply both classes to the element you want..
<span class="class1 class2" />
another is to name both classes when setting the properties
.class1, .class2 {text-indent: 100}
.class2{/*extra properties here*/}
You can define 2 classes in this way
.class1, .class2 { text-indent: 100 }
And it will work for you
Moreover if you want to ad some more in class2 then you can define it
.class2 { /*whatever you want here*/ }
Others mentioned SASS and LESS. Here's the solution of Stylus:
.class1
text-indent: 100
.class2
#extend .class1

!imporant equivalent for HTML class tag?

I'm dealing with a real hash of a site, so this is why I'm asking about this absurd question.
I've looked everywhere to find some sort of way to make a class override another class in the HTML class tag to no avail.
I can either do this, try to untie a ton of spaghetti (which I probably won't be allowed to do anyways), or something anyone else can recommend (would be greatly appreciated).
Is this possible?
class="myClass !important"
If not, is there some sort of equivalent?
Please help! Many thanks in advance!
No, that's not possible. You're going to have to iron out the CSS Specificity by yourself I'm afraid.
If you have the ability to change the HTML templates, you can always go in and add a <div id="override"> or something like that to the outer most wrapper of the page to use as the "master" rule in your CSS classes. Then, in the CSS, you can just add that ID before any of the existing classes or ones that you need to modify.
For instance, if you have the following and want to override the .some-class:
<div class="some-class">Bleh.</div>
And the corresponding CSS:
.some-class { color: red; }
You can wrap the whole thing with:
<div id="override">
<div class="some-class">Bleh.</div>
</div>
And add the #override (or whatever you want to name it) before the .some-class and this rule will take precedence over the other:
#override .some-class { color: green; } /* This will override the red color form the other rule */
.some-class { color: red; }
You can't use !important for entire selectors. You need to find the specific rules you want to override, and use !important on each.
You can add more than one class to a selector as follows:
class="myClass myClass2"
Above is what the class attribute would look like on your HTML element.
As far as the CSS goes, define the classes as follows:
.myClass {
color: black;
font-size: 14px;
}
The above is just a sample of some properties you may have.
Defining "myClass2" after "myClass" in your stylesheet will allow the properties from "myClass2" to overrided the matching ones in "myClass":
//This goes below myClass
.myClass2 {
font-size: 16px;
}
As long as "myClass2" is after "myClass", your font will take the size property of '16px;' The value of "myClass" will be overwritten by that of "myClass2". If "myClass2" comes before "myClass", you can use !important to ensure that style is taken over the one defined later:
//This goes above myClass
.myClass2 {
font-size: 16px !important;
}
Hope this helps.
CSS classes are just a group of styles so you can use class instead of inline style tag.
The !important keyword helps you to override a specific style and not working on classes.
So, for example:
Lets say that we have a css rule on every div somewhere in our CSS file
div{border:solid 1px #ff0000;}
And later on we have this rule:
div{background:#000000;}
Every div in our page will be with border and a background if we want to override the div css rules we need to do something like this:
div{background:none !important;border:none !important;/*...ADD YOUR CSS...*/}
you can create a css reset class to reset all the settings that you want and than add your css

How to differentiate the common css class by using other css class

<div style="position: absolute; left: 0px; top: 5px;" class="v-caption v-caption-top_header">
<div class="v-captiontext">Create User Wizard</div><div style="clear: both; width: 0px; height: 0px; overflow: hidden;">
</div>
</div>
<div style="top: 70px; left: 10px;" class="v-absolutelayout-wrapper">
<div style="height: 5px; width: 1257px;" class="v-label v-label-intro_key intro_key">
</div>
</div>
<div style="position: absolute; left: 10px; top: 55px;" class="v-caption v-caption-intro_key">
<div class="v-captiontext">User Details.
</div>
I have to apply some styles to Create User Wizard text. But I cannot refer v-captiontext css class directly becoz the same css class is used by other text also for example User Detailstext. How can apply changes to only Create User Wizard text.
You can refer to nested classes. In your current HTML you could refer to v-caption-top_header with v-captiontext inside it like this:
.v-caption-top_header .v-captiontext {
...some styles here...
}
or
.v-caption-top_header>.v-captiontext {
...some styles here...
}
(the first of these specifies that v-captiontext is somewhere beneath v-caption-top_header in the DOM, whereas the second one specifies that it is a direct child; ie immediately beneath it in the DOM. The second one is probably preferable, except that it doesn't work in IE6, so if you need to support IE6 then use the first one)
The other options you have would require you to change the HTML code.
You could give the Create User Wizard element a specific ID and use that instead of the class:
<div class='v-captiontext' id='wizard_element'>....</div>
#wizard_element { ..... }
or use multiple classes:
<div class='v-captiontext wizard_element'>....</div>
.wizard_element { ..... }
In this case, the choice between ID or class would depend on whether you is bit of styling on this element is going to be unique - if it is specific to this element then use an ID; if you want to use it elsewhere then use a class.
If you still have problems, you could try using some trickier solutions:
CSS supports attribute selectors, which allow you to select elements based on specific HTML attributes. This can be very useful, but I don't think it'll help you here (since you don't have much in the way of attributes other than styles and classes anyway). Also this again doesn't work in IE6.
Another option could be pseudo-selectors such as :first-child or :nth-child(). Using these you could for example specify that the first matching element gets one style and others get something else. These may actually be useful for you, in conjunction with other techniques above. However you'll have problems with these with all current versions of IE, so probably not recommended.
There's a very good overview of the available CSS selectors, along with which browsers support them at Quirksmode.org: http://www.quirksmode.org/css/contents.html
As the div you want to style a child of v-caption v-caption-top_header but v-caption v-caption-top_header is not the parent of the other div you do not want to touch, this should work:
.v-caption.v-caption-top_header .v-captiontext {
/* whatever style you want */
}
Of course the better approach is simply to add an id="someuniqueid" to the div you would like to style and then add
#someuniqueid { /* style goes here */ }
give it an ID as opposed to CLASS
Is the class v-caption-top_header of the parent div unique? If yes you can use a descendant selector:
.v-caption-top_header .v-captiontext {
...
}
http://www.w3.org/TR/CSS2/selector.html#descendant-selectors

How can I set css for a class in a class?

With this HTML code.
<div class="noote">
<p class="first admonition-title">Noote</p>
<p class="last">Let's noote.</p>
</div>
How can I set the color of Noote to be red with css?
I mean, how can I set something for (div class="noote") and (p class="first") under it with css?
Try this:
/*this will apply for the element with class first
inside the element with class noot */
.noote .first{
color:red;
}
/* If you wanted to apply a rule for both individually
you can do: */
.noote, .first{
border:1px solid red;
}
div.note{
...
}
Refers to the div element that has the class note.
p.first{
...
}
Refers to the p element that has the class first.
div.note p.first{
...
}
Refers to the p element inside note that has the class first.
In addition, if you want to set an element child without setting a class to it,
div.note p:first-child{
/* it refers to the first p that contains noote */
}
#amosrivera's got it.
It's worth nooting that descendant selectors require more CPU. I always use more specific rules where possible. So instead of
.noote .first{
backgorund:red;
}
You could say
.noote > .first{
backgorund:red;
}
A nominal difference in most cases, but still a good habit.
Really?
Descendant selectors are
inefficient... The less specific the
key, the greater the number of nodes
that need to be evaluated.
— Google "Let's make the web
faster" docs
And
Descendent selectors are a major slow
down to the Safari browser
— John Sykes, May 2008
Some performance tests show little impact, and most writers agree that it only makes a difference on very large documents.
But mainly, I'm just going with my programmer instinct — say what you mean, and no more.