BEM: Modifier of a block effects all elements - best practice? - css

What is the best practice if a modifier effects all elements of a block?
In my current project I have a header. This header changes to position: fixed if the user scrolls.
In the header there's the main navigation, the logo, a language switcher and a phone link:
<header class="header">
<div class="header__logo">...</div>
<nav class="nav nav_main">...</nav>
<nav class="nav nav_lang-switch">...</nav>
<div class="header__phone-link"></div>
</header>
On scrolling, the header get's the modifier header_fixed:
<header class="header header_fixed">
<div class="header__logo">...</div>
<nav class="nav nav_main">...</nav>
<nav class="nav nav_lang-switch">...</nav>
<div class="header__phone-link"></div>
</header>
The header looks completely different if it's fixed: the color changes, the main navigation turns to a hamburger icon navigation, the icons of the lang switch become smaller and so on.
Now I could go the nested way in CSS:
.header_fixed .nav_main {...}
.header_fixed .lang-switch__icon {...}
.header_fixed .header__phone-link {...}
...
Or every block or element that changed can get it's own modifier class.
What are your thoughts about that?
Regards,
Marcus

Nesting is just fine here, see https://en.bem.info/methodology/css/#nested-selectors

Related

How to get an Amazon.com type navigation bar (seemingly two navbars wrapped within a single container)?

I want to get the above type of navbar.
What I tried was this
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="row>
<nav class="navbar navbar-default">
<!-- Some stuff like the brand image, search box etc. -->
</nav>
</div>
<div class="row">
<nav class="navbar navbar-default">
<!-- The main navigation stuff -->
</nav>
</div>
</div>
</nav>
but this makes something like this...
How can I remove those gaps without modifying bootstrap.css
The navbar-class has margin-bottom: 20px in bootstrap.css so you need to make an overriding rule there.
But rather than making the rule change to the bootstrap.css file, make another CSS file, eg. custom.css, where you write these new rules. Add this file to your html template after the bootstrap.css and it will override the basic rules.
Make always the new CSS rules to the custom.css, it's much easier to handle.

overflowing navbar in bootstrap

I'm experimenting with Bootstrap 3.2. I'm trying to create a fixed at top navigation bar but I'm running into two problems:
The navigation bar overlaps the content below it.
The navigation bar seems to be going far off the screen to the right. This makes my button in the navigation bar not visible unless the window width is dragged to a smaller size.
For the first problem, I've followed the Bootstrap example tip by adding a class to my css file, including this file below the Bootstrap css file in the html document, and then referring to the class.
.navbar-height{
body{padding-top: 200px;}
}
<body class="navbar-height">
Though, this seems to do nothing (as you can see I specified the number really high hoping to see a dramatic change, which did not occur).
Here's my the navigation bar:
<header id="header-navigation">
<div id="nav-bar-container">
<nav id="nav-bar" class="navbar navbar-default navbar-fixed-top" role="navigation">
<div id="nav-item-container" class="container-fluid">
<div id="drop-down" class="navbar-header">
<button type="button" class="btn btn-default navbar-btn navbar-toggle collapsed" data-toggle="collapse" data-target="#user-dropdown">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div id="home-button" class="navbar-left">
<a class="navbar-brand" href="#"><img alt="Brand" src=""></img></a>
</div>
</div>
<div id="user-dropdown" class="navbar-collapse collapse">
<ul class="dropdown-menu" id="dropdown-items" role="menu">
<li>
<div class="list-group-item">
<div class="row-picture">
<img class="circle" src="" alt="icon"></img>
</div>
<div class="row-content">
<h4 class="list-group-item-heading">Placeholder</h4>
<p class="list-group-item-text">Placeholder</p>
</div>
<div class="list-group-seperator"></div>
</div>
</li>
<li><span class="glyphicon glyphicon-log-out"></span></li>
</ul>
</div>
</div>
</nav>
</div>
</header>
As a quick break down of the above code, I have a <header> tag which will hold the navigation bar. Within this <header>, I have a containing <div> (id="nav-bar-container") which only purpose is to act as a container for the navigation bar (maybe I'll add something else to the header and want to keep the bar seperate). Then, I have the actual <nav> which has the appropriate classes (or so I think): "navbar navbar-default navbar-fixed-top". The next <div> (id="nav-item-container") holds the components of the navigation bar. The following <div> (id="drop-down") contains the button (which seems to disappear at full-screen) and a link with a "brand", which always seems to be visible. The last major <div> contains the "drop down" content for when the button is pressed.
My Question: why is my navigation bar overlapping the content below it and over extending to the right hiding the button?
Ok, first thing, you don't need the <header> tag, so feel free to remove that.
Second, from the Docs on navbar-fixed-top, you need to have padding:
body { padding-top: 70px; }
Notice you applied it to the heading style; that won't work. Apply it to the body and it works fine.
As far as the 2nd issue, I don't actually see any horizontal scrolling when I removed the
<header> tag, so I think that may have been causing an issue.
Checkout this Bootply example:
Bootply Example
To see what I mean. It's your code with the tag removed. Hope that helps!
Change..
.navbar-height{
body{padding-top: 200px;}
}
to..
body.navbar-height{
padding-top: 200px;
}
You want the padding on the body itself. This will push you body down 200px giving you a gutter at the top for your fixed navbar.
most likely you'd want to adjust this padding depending on the actual height of your navbar.
As for problem number two, where I believed the navigation bar to be overflowing off the screen to the right, was just a mistake in the layout of the code. I was grouping the button I wanted to display on the right with the brand in the "navbar-header". What this does is display the brand but use that button only on a mobile screen to hide or show its associated dropdown. That is why I was only seeing the button when I made the width smaller by dragging the window. To fix this problem I removed the button and placed it within the appropriate code block. So, my "navbar-header" now looks like this:
<div id="drop-down" class="navbar-header">
<div id="home-button" class="navbar-left">
<a class="navbar-brand" href="#"><img alt="Brand" src=""></img></a>
</div>
</div>
Now, next within the id="nav-item-container" parent div, I create a list of items (ul). This list contains the items within the navigation bar and has the classes "nav navbar-nav navbar-right". Each list item (li) within this list is an item within the navigation bar. Dropdown buttons and their contents must be contained within the same list item (li). Make sure the parenting list item to the dropdown elements contains the class "dropdown". Then, the button or link should have the "dropdown-toggle" class applied to it. And the dropdown items themselves (which too can be a list of items and often is) should have the class "dropdown-menu". For example:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<span class="glyphicon glyphicon-align-justify"></span>
</a>
<ul class="dropdown-menu" id="dropdown-items" role="menu">
<li>
<div class="list-group-item">
<div class="row-picture">
<img class="circle" src="" alt="icon"></img>
</div>
<div class="row-content">
<h4 class="list-group-item-heading">Placeholder</h4>
<p class="list-group-item-text">Placeholder</p>
</div>
<div class="list-group-seperator"></div>
</div>
</li>
<li><span class="glyphicon glyphicon-log-out"></span></li>
</ul>
</li>
</ul>
Note, in the snippet I didn't include the parenting nav, div, or header so it may not work exactly how it should. Also, I figured the majority of this out on my own by referencing the Bootstrap component page, as well as, the Bootstrap material design page (a plugin to Bootstrap that gives everything the Google Material Design look and feel). So, I'm not sure if all the "rules" I stated are mandatory or if there are other ways to achieve this.
As for problem number one, I just made a silly mistake with the css and the two other answers provided correct ways of fixing it. All I had to do was fix the body css like so:
body{
padding-top: 200px;
}

CSS Overflow: Scroll in wrong place?

I am in the middle of creating a website using Dreamweaver CC 2014. The Homepage scrolls fine, but the About page and Calendar page doesn't scroll at all and cuts off the bottom half that should be displaying. I've read the other threads that say to add the overflow: scroll code to the CSS. I have done that, but it still isn't working and I'm wondering if I have placed the code in the wrong place?
Here is the link to the Calendar page:
http://normajdougherty.com/Calendar.html
Would you look at the CSS and HTML code and let me know what the problem is? Thanks so much.
You have
position:fixed;
Specified in your navigation bar, which is effectively "locking" the page in place. If you set its position to relative, your menu items (which should also not be set to "fixed") are no longer going to be attached to the navbar.
But the way you have implemented the navbar in the first place is kind of kludgy. You don't need a separate div for the blue bar in the background.
Instead of having two overlapping fixed divs, which is a bad practice for several reasons, just place your navigation buttons in a single div with a background color, using the "background-color" property.
Also, the reason it looks "cut off" halfway down is because that's just the size of the image you're using in the background. Consider setting up a color gradient or something, or honestly just leave the background a solid color. Unless you do something particularly fancy, a big static image like that is not going to look the way you want it to.
EDIT: Okay, at second glance, it looks like your entire page is wrapped within the navigation bar div. That's why the whole page is locked in place when "position:fixed" is set. Make sure you close the tag for the navbar before the rest of the page content starts.
But still, you shouldn't have a fixed navbar like that in the middle of the page, as it will scroll down with the rest of your content and just end up looking really bad.
It is because you set
positon:fixed;
in navbar class.
remove it and page will work fine
So remove
position:fixed
from .navbar class in calendar.css
You're facing this problem because the content part of your page is wrapped inside the navbar div which has been assigned a fixed position. You will need to add the intro div and the <iframe> after the navbar div for your website to function properly.
This is how that particular part of code currently looks like on your website (notice <div class="intro"> and the <iframe> is inside <div class="fluid navbar">):
<div class="fluid navbar">
<img src="images/BlueNavBar.png" alt="navigation menu">
<div id="menu">
<ul>
<li>HOME
</li>
<li>ABOUT ME
</li>
<li><a href: "books.html"="">BOOKS</a>
</li>
<li>BLOG</li>
<li>MEDIA KIT</li>
<li>SPEAKER</li>
<li>
</li><a href="Calendar.html" calendar<="" a="">
<li>CONTACT</li></a>
</ul><a href="Calendar.html" calendar<="" a="">
</a>
</div>
<div class="intro">
<p><b>Below is a monthly calendar of the events I will be attending, participating in or speaking. <br>I may also post my blog schedule, contests and other giveaways.</b>
</p>
</div>
<br>
<center>
<iframe src="https://www.google.com/calendar/embed?src=sffk4qmbgj5b1e08d7lkg84rr0%40group.calendar.google.com&ctz=America/New_York" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
</center>
</div>
And this is how you should modify it (both <div class="intro"> and the <iframe> are added after <div class="fluid navbar">):
<div class="fluid navbar">
<img src="images/BlueNavBar.png" alt="navigation menu">
<div id="menu">
<ul>
<li>HOME
</li>
<li>ABOUT ME
</li>
<li><a href: "books.html"="">BOOKS</a>
</li>
<li>BLOG</li>
<li>MEDIA KIT</li>
<li>SPEAKER</li>
<li>
</li><a href="Calendar.html" calendar<="" a="">
<li>CONTACT</li></a>
</ul><a href="Calendar.html" calendar<="" a="">
</a>
</div>
</div>
<div class="intro">
<p><b>Below is a monthly calendar of the events I will be attending, participating in or speaking. <br>I may also post my blog schedule, contests and other giveaways.</b>
</p>
</div>
<br/>
<center><iframe src="https://www.google.com/calendar/embed?src=sffk4qmbgj5b1e08d7lkg84rr0%40group.calendar.google.com&ctz=America/New_York" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe></center>
Add this two styles in at header section of Calendar.html (this code is writing as internal css, because this code don't affect other pages)
#menu {position: absolute; }
.navbar {position: static;}

Style Twitter bootstrap Navigation

How do people typically style the output of the Twitter Bootstrap collapsible navigation?
The standard structure is as follows.
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar" type="button">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
Project name
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
For example, if I would like to style .nav li a, I can do so with that CSS selector, but that also then changes the styling of the mobile navigation. Bootstrap doesn't appear to add any useful combination of classes to denote different ones.
<div class="nav-collapse collapse"> <!-- Closed by button -->
<div class="nav-collapse on collapse"> <!-- Open by button -->
<div class="nav-collapse on collapse"> <!-- Closed by resizing window to > mobile -->
I find myself having to effectively implement the bootstrap styles again for the mobile version because I can't seem to find a combination of classes which allows me to style just the main nav rather than the dropdown. For example, the dropdown can be styled with .nav-collapse.on
This is probably a really simple thing to do but can't seem to work it out!
I have delt with this issue myself and there are range of solutions.
In order I would put them something like:
Involved but worth it - I have switched to a workflow that involves building bootstrap. I'm using bootsrap-sass with compass and grunt etc. This handles the task of minifying, concatenating etc, and in this case all the changes you want to the _variables.scss or .less etc..
Cheap But Effective - I have used a very simple hack to just make a second menu and add .hidden-phone, .visible-desktop etc.. This allows you to also make unique touch buttons and maybe forgo collapse. Kinda like they do here (It's not bootstrap but its the same concept)
Media Queries - My last css in the list is always my responsive.scss or a file full of media queries, this way I can change whatever I want to override from anything done before for whichever device.
Simplest solution would be to wrap the .navbar div for your main nav in a div with a custom class -- like, say, "mainnav". Then you can write styles to things like ".mainnav .nav li a".
If you can touch the bootstrap structure itself, you could skip the wrapper div and simply add the class "mainnav" to the "navbar" div, and then write styles like ".mainnav.navbar .nav li a".
The menu is broken into two parts, a structure and a styling. If you remove the styling you are left with a naked bootstrap menu that is easy to style. Remove the "navbar-inner" call and it will strip out all the styling for you. I just rename the call on the menu div from navbar-innner to navbar-inner_OFF. That shuts off the -inner css and also reminds me I rurned it off when I look at the menu code.

container inside a navbar in twitter bootstrap

I have a following navbar code using twitter bootstrap
<div class="navbar navbar-inverse">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li class="active">Home</li>
<li>Link</li>
<li>Link</li>
</ul>
</div>
</div>
</div>
and the output is
When I remove "width: auto" from ".navbar .container{width:auto}" in bootstap.css the output becomes
and is the output I am expecting.
https://github.com/twitter/bootstrap/issues/2093 shows "width: auto" as an intended feature.What am I doing wrong here?
<div class="navbar navbar-static-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li class="active">Home</li>
<li>Link</li>
<li>Link</li>
</ul>
</div>
</div>
</div>
This should do it
I found another solution to the above issue.
Add navbar-fixed-top class to the main navbar div.
And add
.navbar-fixed-top{
position: relative;
}
to your css rule.
This restricts the menu from pulling it to the left and worked fine while I was developing a theme for wordpress.
If you look at the Bootstrap basic nav bar example you will see that there is a margin on either side of the navbar. This is because for a non-fluid container, your page will occupy a fixed width and the navbar uses that width.
If you want the navbar to extend across the entire page, you need to use a class="container-fluid" but in a fluid layout, the menu items (by default) will flow from the left-hand side of the page.
In your code, you are using both container and container-fluid which is incorrect, and as per the Bootstrap documentation, you need to place the nav in a container - not embed a container in your nav tags.
I solved this by removing the width: auto definition from .navbar .container in bootstrap.css.
Not an ideal solution (editing bootstrap.css in general) but it was much simpler than applying all the responsive widths to the selector.

Resources