I understand that when using BEM, the classnames should not directly reflect the HTML structure, but how should a wrapper element be named? Please ignore my particular syntax(close to SUIT); it still follows BEM, just with a different way of differentiating the elements.
For example:
<div class="?">
<footer class="PageFooter">
<h4 class="PageFooter-brand>…</h4>
<ul class="PageFooter-contactDetails">…</ul>
</footer>
<div>
I would currently class the wrapper in this instance as PageFooterWrapper, but this feels clunky because the wrapper is not independent - it exists purely for the PageFooter. Obviously prefixing everything with PageFooter- is ridiculous, so that only leaves treating the wrapper as a part of PageFooter: PageFooter-wrapper. This irks me as there is an implied suggested applied by this.
So what should the class of the wrapper be?
The way i've always treated it is the wrapper should always be the block so:
<div class="PageFooter">
<footer class="PageFooter-inner">
<h4 class="PageFooter-brand">...</h4>
<ul class="PageFooter-contactDetails">...</ul>
</footer>
</div>
The Block contains Elements so instead of having something around my Block i just followed along with the Element principle and started using inner's instead of containers
I've actually used two classes successfully, my pattern is as follows:
<div class='page-section bem-block'>
<div class='bem-block__element'>
<!-- etc etc -->
</div>
</div>
Effectively using a utility class to perform certain wrapper functions. The css would likely be similar to this:
.page-section {
width: 100%;
}
#media screen and (min-width: 1200px) {
margin: 0 auto;
width: 1200px;
}
I've found this works well in practice. It would also be possible for .bem-block and it's contemporaries to inherit from .page-section.
This solution complements Dan Gamble's.
Related
I'm trying to dive into the BEM methodology. Even though it seems to be the 'must have' methodology for all project sizes, I'm kind of unhappy with it or am I just trying to use it the wrong way?
Using BEM the CSS gets divided into something like this.
.block {
/* Block code goes here */
}
.block--is-hidden {
/* Block modifier code goes here */
}
.block__element {
/* Element code goes here */
}
This seems to be pretty fine for me, as long as you do not reuse some code. Let's assume I'm using Bootstrap or any other CSS Framework/Library. Doing so I just want to use the grid. That being said my markup could look somehow like that.
<div class="container">
<div class="row">
<div class="col-xs-12">
...
</div>
</div>
</div>
According to BEM this would be a no go. Instead all the grid classes should be wrapper up in our corresponding block and element classes. A possible way to achieve this would be through SASS and it's #include. For me this basically results in redundant code.
So my question right now is. Am I missing something? I mean, using BEM while for e.g. loading Bootstraps .container code into every single of my own block styling would just result in an massive output CSS file. Is my approach correct? And if so - would I really sacrifice initial loading time just for the idea of better organized CSS and better readable markup?
Is there a reason your blocks have to begin at the container level? I'm not sure if it's a violation of BEM methodology exactly, but I personally "begin" my blocks more at the html>body>.container level. So:
<html>
<body>
<div class="container">
<div class="cheesecake">
<h1 class="cheesecake__heading"></h1>
</div>
</div>
</body>
</html
With SCSS looking something like:
.cheesecake {
&__heading {}
}
And so on.
I would like to re-order some div using only CSS if possible.
Here is the HTML sample I want to re-order:
<div class="block1">
Block1
</div>
<div class="block2">
<div class="subblock1">S-Block1</div>
<div class="subblock2">S-Block2</div>
<div class="subblock3">S-Block3</div>
</div>
And this is the graphical result I want:
S-Block1
S-Block2
Block1
S-Block3
I already tried playing with display: flex; and order: X but with no success. The main problem lays in the fact that I want to split the block2 before and after the block1. The flex display only allow me to change order of block of the same "level".
I would really like to have a solution that doesn't not use JavaScript to re-write the DOM (by taking subblock3 and putting it elsewhere to please my CSS) if possible.
It appears this is not possible and javascript is not an option for my problem.
Here is the sample code I used (jQuery needed).
$(".subblock2").prependTo(".form-wrapper");
$(".subblock1").prependTo(".form-wrapper");
Here is an HTML fragment:
<div class="wrapper">
<div class="ebook">
<div class="page"></div>
</div>
<div class="book">
<div class="page"></div>
</div>
<div class="document">
<div class="page"></div>
</div>
</div>
I want to match all divs with the page class with parents divs having ebook or book classes only. This selector can be used:
div.ebook div.page, div.book div.page
However is there a CSS engine suporting the following syntax ?
(div.ebook, div.book) div.page
or better
div.?book div.page
I'm not interested with a solution like this: div:not(.document) > div.page.
The proposed syntax takes the form of a functional pseudo-class called :matches():
/* As this is a pseudo-class, you can make it a little DRYer by saying
div:matches(.ebook, .book) div.page instead */
:matches(div.ebook, div.book) div.page
If you really want to get technical, Firefox implements it as :-moz-any():
:-moz-any(div.ebook, div.book) div.page
and Chrome implements it as :-webkit-any():
:-webkit-any(div.ebook, div.book) div.page
(and these actually came first prior to the selector being specced as :matches())
But if you're using them in CSS you will have to duplicate your rulesets because of certain CSS parsing rules, which is as good as not using them at all (in fact, worse). These selectors are meant for internal use only, not for production.
What you currently have is the only viable option for now.
If you want to cheat a little, you could use a substring attribute selector, but that assumes each of those elements will have exactly one class only, and no other class names will match by this particular substring (this is similar to the div.?book example you have, but it comes with the limitations of an attribute selector that are not present in a class selector):
div[class$="book"] div.page
Personally, I'd just stick with the verbose option because it's more robust.
Check out this Fiddle that should do what you're looking for:
http://jsfiddle.net/Delorian/L44u0p8r/
div[class$="book"] {
background-color: yellow;
}
Further details: https://stackoverflow.com/a/9836182/3264286
There is no such thing as an OR selector in CSS, except for as in the example you gave, where a comma (,) can be used to separate multiple selectors e.g;
div.ebook div.page,
div.book div.page{
// CSS properties
}
I am trying to create an accordion menu with multiple floated elements. I want all of the inactive menu items to collapse to a small fixed width (40px or so) and the active item to expand to the remaining width. I want the menu to be responsive/elastic, so only the inactive menu items will have fixed widths.
Below is an example of what I want my menu to look/function like (without using jQuery to set the widths)...
Accordionza - CodeCanyon.com
I was able to accomplish the desired effect when only two menu items are displayed by floating one of the elements and giving it a fixed width, while NOT floating the elastic item and giving it a width of 100%.
Two Columns (Works)
<style type="text/css">
#one {
float:left;
width:40px;
}
#two {
width:100%;
}
</style>
<div class="row">
<div class="col" id="one">One</div>
<div class="col elastic" id="two">Two</div>
</div>
Four Columns - Elastic In Between (Does Not Work)
<style type="text/css">
#one, #three, #four {
float:left;
width:40px;
}
#two {
width:100%;
}
</style>
<div class="row">
<div class="col" id="one">One</div>
<div class="col elastic" id="two">Two</div>
<div class="col" id="three">Three</div>
<div class="col" id="four">Four</div>
</div>
Please note: applying float:right; to the elements to the right of the elastic item did not work either...
The problem is that if the elastic element is NOT on the end of the row, then the menu items do not remain on a single row. Please examine the fiddle below to see what I mean...
jsfiddle
So how do I apply this desired elasticity to the elements that reside in between their siblings? I really really want to keep the markup as simple as possible. Thanks in advance!
Update: I am getting close to a solution, however there is a slight problem with every method I've attempted. I will break them down, along with the issues I'm running into with each one.
METHOD 1: display: table-cell; (Suggested by onetrickpony)
Seemed like the answer, however there will not always be contents (text or html) inside the slide elements, and elements formatted with the display: table-cell; property do not recognize applied widths unless there is content inside of them. So this only works if I have content inside the slide... (I could modify the markup of my slider, but I would like to keep it the way I have it).
METHOD 2: CSS calc() (Also suggested by onetrickpony)
Not supported by some of the browsers I would like it to be... CaniIUse.com Browser Support Chart for calc(). Another excellent possibilty! One I did not know existed, and could be utilized if I made a fallback JS script for older browsers (want to avoid).
METHOD 3: Flexbox (Also suggested by onetrickpony)
Probably my favorite solution, but limited support is making me timid. Also could be used along with a fallback script. I learned about this a while back, and this is the future of CSS and layouts. Our salvation! Can't wait for full support...
METHOD 4: jQuery (Suggested by Tomasz Golinski)
What I was originally going to use, but decided I wanted to see if there was a CSS method that could be used instead. I have had some issues when using jQuery to set the width of elements. Mainly when the container is resized, and the script calculates the appropriate width while the container is resized.
So, the kind people who responded to my question have provided me with viable solutions to this issue. Any of the below is certainly an acceptable method to do what I am asking. I am simply seeking an answer that is more of a common CSS method. I am hoping that it is possible to accomplish this with some combination of styles I have not tried. I will admit I think Tomasz is correct- it cannot be done. I am leaving this question open just in case someone has a solution for me. Both Tomasz and onetrickpony have given me great answers. But I am still seeking a CSS-only solution that is widely supported by older browsers- and new, that I do not need to include a secondary script for, and that works without the need for characters inside the elements. Just want to see someone prove us wrong (that it is possible with good old fashioned CSS). If this magic answer does not come, I will be marking onetrickpony's answer as the best solution due to the fact it is CSS based, and he provided multiple solutions that are clean and simple. A combination of his flexbox CSS and Tomasz jQuery (as the secondary script) will most likely be what I use. Thanks!
If you're set to use floats, calculate the width of your "elastic" column by subtracting the widths of other columns from 100%. Example:
<div class="row cols-4">
<div class="col" id="one">One</div>
<div class="col" id="two">Two</div>
<div class="col elastic" id="three">Three</div>
<div class="col" id="four">Four</div>
</div>
CSS:
.cols-4 .elastic{
width: calc(100% - 45px * 3);
}
/* add more rules for other possible variations here */
http://jsfiddle.net/QM4LZ/
But a cleaner and easier approach is to use flexible boxes. This is exactly what they were designed for.
.row{
display: flex;
}
.col{
flex: none; /* <- don't flex */
width: 45px;
}
.elastic{
flex: auto; /* <- flex */
width: 100%;
}
http://jsfiddle.net/F7sxU/
It's also possible to achieve this with tables (fiddle), but you'll most likely run into some limitations when adding the real content and you need more wrapper elements.
the previous answer does resolve the issue however there are some problems with #onetrickpony's solution
example #1 will not work properly with dynamic number of items.
example #2 in most browsers it will work but not all browsers do support flexible boxes.
here is simple javascript code
jsFiddle: http://jsfiddle.net/aQEt3/5/
var count = $('.row').children().length; // counts how many items are in the entire row
var totWidth = $('.row').width(); // checks total width of the row
var elWidth = totWidth - ((count - 1) * 45); // counts how wide should be the elastic it
$(document).ready(function () {
$('.elastic').css('width', elWidth); // when document is ready, apply the new width to the elastic
});
beware, this is very simple code and there will be some issues if:
*there are 2 or more .row items
*you have more than one elastic class
In class we are teached to avoid creating ID's in your HTML so you can use them to identify that element in your CSS file. Instead we must use selector specifity as much as possible.
Take for example this simple HTML:
<body>
<div>
<div>
<div>
The div you want to style.
</div>
</div>
</div>
</body>
Is it better to use this:
body > div > div > div{
color: blue;
}
or give the element an id (let's take 'middle') and use this:
#middle{
color: blue;
}
What are the differences (if any at all) performance and usability wise?
The difference in speed between IDs and Classes in modern browsers is so negligible in real world situations it is really not an issue. Therefore current main-line thinking is to use classes where extra clarity and specifity is needed. This way you avoid specifity wars and balances maintainability with code purity.
<body>
<div>
<div class="more-specific-if-needed">
<div class="middle">
The div you want to style.
</div>
</div>
</div>
</body>
.make-more-specific-if-needed .middle {
/* cool styles */
}
Or even use chained selectors to gain extra specifity. You could then split styles in to separate structure based build styles and appearance based theme styles.
<body>
<div>
<div>
<div class="semantic-role theme">
The div you want to style.
</div>
</div>
</div>
</body>
.semantic-role.theme {
/* cool styles */
}
For further reading:
http://csswizardry.com/2011/09/writing-efficient-css-selectors/
Why do browsers match CSS selectors from right to left?
Performance wise it's fastest to get an element by its id than it is to traverse the dom.
From a usability point of view I would be careful using too many id's since they can be only used once for an element.
So it's a question of what you think is more important and how many items we are talking about. Is the speed gain worth the losing of re-usability
Much better to use ID. Performance difference is minimal, and not the important point. I think code readability / maintainability is more important.
One advantage of using ID, is that you could move your element to a different part of the page, and it would retain it's style rules - without counting the containing elements.