It is easy to use BEM for fixed layouts. What is about css styles structure for adaptive web pages with media queries?
html sample:
<div class="t-news">
<div class="t-news__post b-post">
<div class="b-post__title"></div>
<div class="b-post__text--green"></div>
</div>
<div class="t-news__post b-post--small">
<div class="b-post__title"></div>
<div class="b-post__text--red"></div>
</div>
</div>
less sample:
.t-news {
&__post {
//some styles
}
}
.b-post {
&__title {
//some styles
}
&__text {
//some styles
&--red {
//some styles
}
&--green {
//some styles
}
}
&--small {
//some styles
}
}
Should I put media queries inside or outside my blocks?
In my experience, I realized that blocks shouldn't be responsible for their widths or margins for the sake of flexibility and modularity. Having "elastic" blocks in a project allow them to be moved around to occupy different areas (with different sizes) of a page without breaking functionality or layout. As for the margins, it's easier to keep consistent spaces between the blocks if they are defined on a higher level: a template block like, I assume, t-news
is (considering the "t" is for template).
BEM is all about modularity, every piece of code that is related to a specific block stays in the block's folder in the file system, so it shouldn't be different with media queries, that are only a part of the CSS. The important thing is to know what the CSS is doing, for example: if a set of rules is defining areas and margins in a template, whether it needs media queries for that or not, these rules should be a part of the block that is responsible for these definitions.
This approach may generate a lot of media queries, and there may be a concern with rendering performance, but, according to this article, multiple media queries may affect performance only if they are different from each other. Repetitions of the same rule, like @media (max-width: 850px)
, will be serialized and interpreted as one.
This way, media queries related to areas and margins go in the template block, and additional media queries related to the components themselves, go in the components blocks. Since the template is responsible for sizes, I would change the "small" modifier, in your example, to the template block.
Also, I would reconsider using green
and red
as modifiers, since colors may change during the lifetime of a project. I suggest trying something that doesn't describe the appearance of the elements, like correct
and alert
.
Finally, remember that modifiers should folow element classes in the HTML, like b-post__text b-post__text--alert
.
Here's your updated code:
Html:
<div class="t-news">
<div class="t-news__post b-post">
<div class="b-post__title">Title 1</div>
<div class="b-post__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget ligula eu lectus lobortis condimentum. Aliquam nonummy auctor massa. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla at risus. Quisque purus magna, auctor et, sagittis ac, posuere eu, lectus. Nam mattis, felis ut adipiscing.</div>
</div>
<div class="t-news__post b-post">
<div class="b-post__title">Title 2</div>
<div class="b-post__text b-post__text--correct">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget ligula eu lectus lobortis condimentum. Aliquam nonummy auctor massa. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla at risus. Quisque purus magna, auctor et, sagittis ac, posuere eu, lectus. Nam mattis, felis ut adipiscing.</div>
</div>
<div class="t-news__post t-news__post--small b-post">
<div class="b-post__title">Title 3</div>
<div class="b-post__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
</div>
<div class="t-news__post t-news__post--small b-post">
<div class="b-post__title">Title 4</div>
<div class="b-post__text b-post__text--alert">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
</div>
</div>
Scss:
.t-news {
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
margin: -0.5rem;
&__post {
margin: 0.5rem;
width: calc(50% - 1rem);
@media (max-width: 800px) { width: calc(100% - 1rem); }
&--small {
width: calc(25% - 1rem);
@media (max-width: 800px) { width: calc(50% - 1rem); }
}
}
}
.b-post {
box-sizing: border-box;
border: 1px solid #eeb;
background: #ffc;
padding: 0.5rem;
&__title {
font-size: 1.5rem;
@media (max-width: 800px) { font-size: 1.25rem; }
}
&__text {
font-size: 1rem;
&--correct {
color: green;
}
&--alert {
color: red;
}
}
&--small {
border: none;
font-style: italic;
}
}
Hope this helps.