EDIT :
Since asking this question, not only have I realized that there can only be one modifier per modifier class, but I've also found out that the BEM website itself recommends using extra classes for modifiers, so I've officially adopted that method instead.
I've been using SASS with BEM for a little bit, and I'd like to know what are the pros and cons of using multiple classes for modifiers vs #extend-ing the respective block/element class. Is there one that's generally favored over the other ? (considering I won'be be including classes across #media queries [should it even mater ?])
Example of multiple classes :
<div class="btn btn--admin btn--primary">
VS
Example of #extend-ing :
.btn {
// ...
}
.btn--admin {
#extend .btn
// ...
}
.btn--primary {
#extend .btn
// ...
}
Edit
I didn’t get the point of the question at first. After the explanation, here goes my answer.
The result is the same, but using multiple classes for modifiers gives a more granular control in a non-css compilation or edition way (you can change element properties without having to re-compile the sass code or edit your css). Also it will provide a more verbose reading of the html code. By reading btn btn-primary disabled you will know, without having to use the inspector o going to the css code, that you have a button, with a btn-primary style and that the button is disabled. You can get more information there than on a single class button extending the rest of the classes. This is a more suitable approach if someone else is going to use your code or work on your project/website or to build an easy to use framework for example.
If it’s just for a small project/website with minor maintenance/update, using the extends will be a good option too. Sometimes there is no need to fill up the html with lots of classes for each element.
The first approach will result in a smaller css and more verbose html. The second option will increase you css size while creating a more “abstract” code reading.
Using multiple classes is more scope dependent that extending a base class or even a non populated extend (defined as %myextend { ... }.
Consider de following scenario: you have several classes and all share some properties at a different nesting levels (or scope) and event thru different breakpoints. Using multiple class definition will require a lot of code and exceptions to be able to group all the classes together and will require you to duplicate the code (in case of sharing the same code across multiple media queries).
.base,
.parent .another,
.more-clases {
// shared properties
}
#media (your-query) {
.specific-query-class {
//shared properties (repeated)
}
}
In that case you won’t be able to group all your classes definitions in one single definition scope as you could do using #extend:
%my-extend {
// shared properties
}
.base,
.parent .another,
.more-clases {
#extend %my-extend;
}
#media (your-query) {
.specific-query-class {
#extend %my-extend;
}
}
That will allow to share/group properties blocks across different nesting levels and media queries definitions without repeating your code blocks.
Defining the extend with % instead of . will allow to share the properties block between different nesting levels and media queries definitions. The main definition of the extend won’t be compiled to css: the definition block will be copied to all the extended rules. Using . for the definition will output the mail properties block to css and will group all the extended classes together, but with this type of extend you can extend thru different media queries.
Hope it helps.
I think you want to extend multiple multiple classes
.btn {
}
.btn__admin {
}
.btn__download {
//to extend .btn.btn__admin
#extend .btn;
#extend .btn__admin;
}
Related
Inside vaadin-grid.css I managed to get the #table element which contains the grid's rows
and with for example
#table th {
backround-color:green;
}
I can change its color.
Now I need to do that only when the page is printed.I tried adding inside vaadin-grid.css
#media print {
#table th {
backround-color:green;
}
}
but that has no effect.Note that I print the page using javascript print().
I added an id="viewfgrid" (as seen in the screenshot) to the enclosing grid and with that now when I add
inside shared-style.css
#media print {
#viewfgrid {
outline:green;
}
}
I can access and change the grid when printing.
However I can't access the inside table with the rows.I tried various variations like
#media print {
#viewfgrid #table {
background-color:green;
}
}
#media print {
#viewfgrid :host > table {
background-color:green;
}
}
but no effect.
How can I access that table ?
Also as a secondary question why can I access #table from within vaadin-grid.css without prepending :host ? when I do that , it has no effect
thanks
I’m not sure why #media print would not work from within the Grid’s shadow DOM styles. Did you try in different browsers? I wonder if there’s some browser bug/limitation here, similar to the fact that you can’t define a #font-face inside shadow DOM.
Also as a secondary question why can I access #table from within vaadin-grid.css without prepending :host ? when I do that , it has no effect
The host selector targets the same element as the #viewfgrid ID. To select a host element with a specific ID, you can use :host(#viewfgrid) inside the shadow DOM styles.
Notice, that you should not rely on any ID, class name, or raw tag name selectors when styling Vaadin components (for example #table or th. Those are considered internal implementation details / private API, and can change in any release. You should only rely on the :host(...) and [part~="..."] selectors and state attribute selectors (for example, [focused]).
If there really is a limitation in using #media print inside shadow DOM styles, I think your best option is to use the ::part() selector, which allow you to style named parts inside the shadow DOM from the outside/light DOM styles. That is actually a more robust method than relying on injecting styles into the shadow DOM (via the frontend/mytheme/components/vaadin-grid.css file).
styles.css:
#media print {
#viewfgrid::part(cell) {
background-color: green;
}
}
The API docs show all available parts of the Grid (look for the "Styling" section): https://cdn.vaadin.com/vaadin-web-components/23.2.0-alpha3/#/elements/vaadin-grid
Grid is by design not very printing friendly as it has been designed for "infinite vertical scrolling". You wont for example have headers and footers per page. If you want to include "report" functionality to your application, it is better approach to create separate report view that is designed printing friendly instead of screen use. This will allow you to use different layouting and components in it. You can for example generate multiple Grid's for each page. Or use BeanTable component from Directory, which generaters HTML Table without shadow DOM.
Because apparently you can't access the shadow dom from CSS when there's no 'part' tag on the element,as is the case with this table,I got it by using Javascript as in :
UI.getCurrent().getPage().executeJs("const tabledom = document.querySelector(\"#viewfgrid\").shadowRoot.querySelector(\"#table\");
tabledom.style.cssText+='.....' "
So now this snippet is called when the user clicks on a Print button and you can do whatever with the element's style.In my case I flatten the table so that it can be printed without the scrollbar intervening.
I am working on a project that contains some complex mixins. We are using a modified BEM class naming strategy, so a typical mixin looks something like this:
#mixin mixin__nestedHeader {
color: grey;
&__title {
font-size: 1.2em;
}
&__message {
font-size: 0.6em;
}
}
And this would style a block of HTML that looks like this:
<div class="header">
<h4 class="header__title">Title Text</h4>
<div class="header__message">Message Text</div>
</div>
So, the problem we are running into, is that the mixin determines what our HTML structure is. On one hand, we want this HTML to always be styled the same since we're using a mixin, so needing it to always be the same is not the end of the world. But, if this HTML code is already nested inside an "item" block, it causes our classes to be "item__headerTitle" and "item__headerMessage" which makes the mixin not work.
Now, we can add the classes using arguments on the mixin, which is what compass does. But, that makes the mixin more complex to use.
I'm wondering what are everyone's thoughts on letting a mixin dictate what HTML structure is used. Do you just deal with it since you're getting the benefit of using the mixin? Or is it something that is a deal-breaker for you which causes you to stay away from more complex mixins that style multiple elements with specific class naming. There are no wrong answers, we are just trying see what people think.
TL;DR: With gratuitous code-commenting, I think dictating the structure in the styling is fine. Also, having your mixin accept arguments makes it more flexible to use, but exponentially more complex to build/maintain. Really think hard if you're ok with that tradeoff.
The nice thing about working in any sort of environment/language that will ultimately be compiled or minified before it gets to production, is that it allows you to be incredibly verbose with your code comments. At best, they can be an incredibly helpful insights into how stuff works. At worst, they are easily ignorable and get stripped when compiling for production anyways, so there really isn't a cost. SASS is no exception.
With that preface in mind...
I have done something similar in the past where we were using placeholder selectors as a base style for a particular family of elements that would each get extended with their own unique styles given the situation. The structure of the markup that those elements needed to use, along with how to write and an extended style was all included within that particular SASS include. It ended up looking something like:
%full-width-story-block {
/* Can be included with article.story-block elements which need to occupy their container's full width.
See "Usage" section after the style definitions for notes & examples. */
flex-basis: 100%;
display: flex;
& > * {
#include make-col(6);
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
}
& > div {
padding-left: $story-block-spacing*2;
}
& > a { display: block; }
#include media-breakpoint-up(md) {
h3 { padding-top: 0; }
}
#include media-breakpoint-down(sm) {
flex-wrap: wrap;
& > div {padding-left:0;}
& > * {
#include make-col(12);
}
}
/* Usage :
+ Ensure that the element is rendered on the page in the following pattern:
(note the div containing everything but the 1st anchor/image tags.
This is generally not included when story-block elements are used in "Content Walls")
<article id="post-4321" class="story-block">
<img src="story-pic.jpg" />
<div>
<h3> Story Title </h3>
<p>A short excerpt from the article...</p>
<div class="save-article">
<a class="save-to-pocket" href="/pocket/url"/> <svg>...</svg></a>
<a class="save-to-instapaper" href="/instapaper/url"/> <svg>...</svg></a>
</div>
</div>
</article>
+ Extend the styling to the element container:
.container-needing-full-width-story-block {
.story-block { #extend %full-width-story-block; }
}
*/
}
The big thing was communicating that the info was there and being consistent in the implementation. There were a couple of different families of components that shared that sort of structure, and they each had their required markup structures and process of extension laid out in the code comments in a similar manner. This made it easy for other dev to come along and start using & extending the structures we had already spent time setting up.
Also, the fact that all of this documentation (for a lack of a better word) existed within the codebase itself means that all this knowledge would be ported around with the project files by default. So in 2 years when a fix or update needs to be applied, as long as we have the code-base, we're not trying to track down some obscure internal knowledge-base/wiki article or the devs who originally built it.
All of that being said, I would caution you on writing something that would accept arguments. In theory it does allow for more flexibility in the structure of markup, but that flexibility comes at the cost of increased complexity in building and maintaining that mixin. I've seen/built things like that which had good intentions, but ultimately ended becoming very "switch case"-ey, with each usage of the mixin elsewhere in the project requiring changes to the mixin itself to handle that particular situation's idiosyncrasies. Just something to think about...
Let I have 2 classes named class1 and class2. Also I have an element with id="responsive_element". What I want is to assign class1 to this element when screen size is below 768px and class2 otherwise.
I can do this in Less like:
#media screen and (max-width:768px){
#responsive_element{
.class1()
}
}
#media screen and (min-width:769px){
#responsive_element{
.class2()
}
}
Is there any "CSS only" way to achieve this?
Edit: I think I couldn't explain my question clear enough. I am already able to do this by compiling less, but the size of css file grows for the long class definitions and using them too much. I want to handle it with simply changing class of the element .
Except for the .class1() and .class2() calls, your Less code already is CSS. Specifically, the #media queries that apply styling based on screen size aren't Less-specific. So, for example, the following is pure CSS:
#media screen and (max-width:768px){
#responsive_element{
color: blue;
}
}
#media screen and (min-width:769px){
#responsive_element{
color: red;
}
}
If you want to convert your Less into CSS, all you need to do is copy the CSS code from .class1 and .class2 into the place of the .class1() and .class2() calls. In fact, since Less is implemented as a converter to CSS, you can just use the online converter at LESS2CSS to do the conversion for you.
If you're asking if there's a way in plain CSS to write these queries so that they use an existing .class1 and .class2 style definition without copying, then I believe the answer is no. The main reason Less was invented was because CSS doesn't support this kind of reuse of styling information.
If you mean, is there a way to use CSS alone to change the class of an element in response to changing screen sizes (literally, adding or removing new classnames to the element's HTML "class" attribute so CSS for different classes will take effect on that element), then the answer is simply "no, you cannot do this with CSS alone".
(Less can't do this either. Your original Less code doesn't change the class attribute of the element, as you can plainly see by looking at the generated CSS. It just uses classes as a handy trick to name sections of shareable CSS.)
The only way to change the element's class in the manner you seem to want is to make changes to the DOM, which you can obviously do via JavaScript but not with CSS alone.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
It seems there are two major schools of thought on how to structure CSS and HTML. I was taught to keep the HTML as clean as possible, and all things stylistic should be on the stylesheet. This has served me well thus far, but with this approach I often notice redundancies and inefficiencies.
I read up on the atomic approach, and I really like the idea. It seems to be the method I naturally gravitate toward anyway.
My question:
Which way is really faster, considering the two following blocks of code:
HTML:
<div class="main">
<h1 class="m-10 theme-c1">header with margin and theme color 1</h1>
<p class="fz-1 theme-c1 m-10">paragraph with font-size 1em.</p>
<div class="m-10">
<p class="fz-1 m-10">blah</p>
<p class="sub-paragraph">Sub paragraph</p>
</div>
</div>
Stylesheet:
/*margin-left rule*/
.ml-10 {margin-left:
/*font-size rule*/
.fz-1 {font-size:1em}
/*theme color*/
.theme-c {color: #333};
/*display rule*/
.dps-blk {display: block}
/
/*sub paragraph styles*/
.sub-paragraph {
margin-left: 10px;
font-size: 1em;
font-color: #333;
}
Elements in the HTML above all get whatever style they need, and the styles above are non-descendants except for .sub-paragraph.
So is it faster for each element to cherry pick which styles it needs, or is it better to just give it a chunk of styles (like for .sub-paragraph)? With .sub-paragraph, I can see how it only takes one match to get all the styles. The trade off, however, is that there isn't much else you can do with that set of styles except use it on sub-paragraph, or override some of its properties with another rule when applied to something else.
I'm think with these two approaches, it's a decision on whether to the cost on data size or on processing time.
Edit
I appreciate all the feedback. I forgot to mention that I'm specifically interested in the processing speeds of the different approaches.
This is interesting nonetheless.
If you were to begin cherry picking individual styles, you would end up with a stylesheet like:
.red{ color: red; }
.green-background{ background: green; }
.w500{ width: 500; }
.ml20{ margin-left:20px; }
Which is not very maintainable.
It sounds like what you are looking for is a way to extend certain classes (i.e. .sub-paragraph) with pre-existing classes, adding the styles of other classes into .sub-paragraph. SASS's .extend directive is a great way of doing this.
Sass and other preprocessors are great at merging the ideas of maintainable code and semantic code together.
Edit 1:
If you are looking into which method (more classes/less properties or less classes/more properties) is faster, I would suggest doing some testing with Chrome Dev Tools' Timeline. The two methods of coding aren't the only thing that are going to affect how fast a page renders/paints, so it is always a good idea to test these if you are concerned about speed.
I organize my CSS by grouping certain types of classes together. When creating CSS classes I ask myself, am I going to reuse this class definition for anything else? Is it logical for me to separate this class' definition, will someone who has to read this after me want to shoot themselves?
Basically I would say, go for maintainability, an extra 1Kb on your Css will not choke anyone.
CSS is designed to use classes for certain groups of styles. The .sub-paragraph method is usually way better than the seperate classes method. If you are going to assign classes for each style seperately, you might as well just use inline styles, via the style attribute. You should usually try to avoid that for maintenance reasons though.
I think there is a place for both.
I don't feel that the abstraction belongs at class names like .p1-gr-brdr, though.
If you're writing very tightly-composed, atomic HTML partial-templates (for things like AngularJS directives), then you'd likely get more mileage out of .title, .subtitle, .just, .content, where you can specify very specific output for those components.
Changing those components will be very simple and straightforward, as they're so compact and self-contained.
And if you find yourself in a position where you need to override one, to compose an inherited class, then you either have the option of composing a new class-name, which now might not be 100% semantic/generic (".big-green-subtitle"), but is still 100% self-contained for those moments where you want your special-cases to feel loved, too...
...or you can then specify behavior with a second-level selector.
If your .header has a padding, but you don't want your .update > .header > .subtitle to be subject to that padding-bottom, on mobile-phones, in landscape orientation, on Tuesdays, then you can simply have an exception which states .update > .header { padding-bottom : 0; }.
Otherwise the cascade will continue as normal, and things will either pile on top of one another, or you will cancel out side-effects with specialized classes which cover the same properties...
Otherwise, I don't see why all CSS sheets don't look like:
.p1-br { border-width : 1px; }
.p2-br { border-width : 2px; }
.p3-br { border-width : 3px; }
.p4-br { border-width : 4px; }
.gr-br { border-color : green; }
.lgtgr-br { border-color : lightgreen; }
.sfmgr-br { border-color : seafoamgreen; }
.aqmr-br { border-color : aquamarine; }
.em1-wd { width : 1em; }
.em2-wd { width : 2em; }
.em3-wd { width : 3em; }
.rm1-wd { width : 1rem; }
.pc1-wd { width : 1%; }
...et cetera, until you've written out every atomic option you could possibly want, for any theme your project (and all of its components) might want to support, across all platforms.
That seems like a terrible use of your day, to write a unique class-name for every possible edge-case out there:
<div class="pos-rel
p1-br
p18-ng-tp
mrpc12-br-r
lggr-bg
bg-im-spr-id-123
pc15-bg-im-algn-lf
ofl-x-hd
ofl-y-aut
brd-bx">
Seems hefty for a single div, for instance.
This would not, however, be a bad idea, if you could write CSS rules, give them to classes, where you expect flexibility, and later had the hard-numbers to those rules.
Such that, say, you write out a class which expects to treat height in rems, margins in percents, border-radius in ems, will take a background-colour and an image-sprite (say it's a backdrop container for a corporate/retail site, with a watermark and logo, where other content will scroll above it).
Now you want to reuse that set of classes on the same component, but for a different client...
It would help if you could simply have some variables, which could live in a separate file, and be referenced by your classes, so that your units don't necessarily need to change, but you can modify all of your hard-coding stuff in one or two places, and swap different variable values in for different clients as easily as pointing at a different sheet...
...but that's what SASS already does, if you take the time to sit down and figure out how you want to engineer something, and make your build process adhere to that desired outcome.
Say I have the following LESS:
#accent: #00aa22;
.mainStyle
{
border-radius:0.5em;
border: 1px solid #accent;
}
#someElement
{
.mainStyle;
}
I only ever use .mainStyle in my LESS, and never actually use it in my HTML for any elements. It's just being used to avoid repetition inside my LESS file.
In the generated CSS however, .mainStyle is redundant, since it's only used within my LESS.
Is there a way to exclude that class from the generated CSS while using it within the LESS?
Got this 20 seconds after asking the question...
You can make the class a parameterless mixin by adding brackets to the end:
.mainStyle()
{ ... }
Now its contents only appear where it's used in your LESS and never as a class in its own right in the generated CSS.