Inline block challenges and suggestions for the layout - css

I keep reading articles that floats are outdated and that using inline-block solves problems such as having to use clearfix and a few more. These articles go on to justify inline-block by showing the same example: three squares that are aligned middle. In trying to use inline-block to create a navbar, I come across many problems. My navbar layout looks like such:
<nav id="main-nav" class="navbar">
<div class="logo">
<!-- image -->
</div><!--
--><div class="navbar-header"><!--
--><button type="button" class="navbar-toggle closed">
<span class="sr-only">Toggle navigation</span>
<i class="fa fa-bars"></i>
</button>
</div>
<div class="navbar-collapse navbar-sidebar">
<ul class="navbar-nav">
<!-- list-items -->
</ul>
</div>
</nav>
In order to align the logo left and the navbar-toggle button right, I had to use text-align justify and some special markup, which I find just as obtrusive as clearfix (Align two inline-blocks left and right on same line):
.header {
text-align: justify;
/* ie 7*/
*width: 100%;
*-ms-text-justify: distribute-all-lines;
*text-justify: distribute-all-lines;
}
.header:after{
content: '';
display: inline-block;
width: 100%;
height: 0;
font-size:0;
line-height:0;
}
.logo {
display: inline-block;
vertical-align: top;
}
.navbar-header {
display: inline-block;
vertical-align: middle;
}
My navbar is very similar to Bootstrap's. At small screen sizes, I want my navbar-toggle button to be centered in the navbar area. Vertical align: middle, however, would align this button to the middle my logo, which will be shorter or taller than the navbar, and which I also want aligned to the top of the navbar. Inline-block doesn't allow me to vertically align my content to the parent container, which seems to make it a non-viable option in many layouts. Is there some sort of solution where I can align my content to the container, rather than the sibling elements? I've been experimenting with setting different line heights and vertical-aligns.

If you have followed the comments above, there are many question being asked. I'll try to summaries most of it.
For display:inline-block, the vertical-algin property only affects the position of the element itself, and relative to the position of the siblings (the tallest sibling especially).
Percentage height like height:100%, only works with fixed height of parent container, or all percentage height that is set all the way back to <html> tag. But excluding positioned (relative, absolute etc.) elements, and viewport units vh, and maybe some other cases.
For display:table-cell, the vertical-algin property affects all the child elements, again excluding some positioned ones.
I think CSS table is easiest way to get your desired layout done in this case. Since you can easily have both vertical and horizontal alignments set on it. Here is a simplified workaround.
JsFiddle Demo
.nav {
border: 1px solid red;
display: table;
width: 100%;
}
.nav > div {
display: table-cell;
vertical-align: middle;
}
.logo img {
display: block;
}
.menu {
text-align: right;
}
.menu span {
border: 1px solid blue;
}
<div class="nav">
<div class="logo">
<img src="//dummyimage.com/50"/>
</div>
<div class="menu">
<span>Menu</span>
</div>
</div>

Related

Sticky element inside flexbox (not in combination with)

Many similar questions have been posted to try and achieve position sticky with an element that has flex rules applied (e.g. this post is one of many that I tried the answers from), but my aim is to apply position:sticky to a child of a flex element.
I have a two-column layout with a menu on the left. The idea is that when the page is scrolled down, the blue-colored menu stays at the top (although the image above should scroll upwards, leaving just the menu visible in it's place).
However, no matter of which combinations of align-self I apply, the menu still disappears vertically upwards with the image.
If its possible to combine flex with sticky, then I'm hoping there's also a solution for the child element.
Fiddle here using SCSS
.PageContainer {
.OuterContainer {
display: flex;
flex-wrap: nowrap;
gap: 1em;
.SideOne {
background-color:#fee;
align-self: flex-start /* Solution from https://stackoverflow.com/questions/44446671 */;
width: 10em;
.CompanyLogo {
img {
width: 100%;
}
}
.MyStickMenu {
border:1px solid blue;
background-color:#eef;
position: sticky;
top: 0;
}
}
.SideTwo {
background-color:#ddd;
flex-grow: 1;
flex-shrink: 1;
}
}
}
<div class="PageContainer">
<div class="OuterContainer">
<div class="SideOne">
<div class="CompanyLogo">
<img src="https://via.placeholder.com/250x100.png" alt="" />
</div>
<div class="MyStickMenu">
<h2>
Not-so Sticky Menu
</h2>
<ul>
<li>
Home
</li>
<li>
Away
</li>
</ul>
</div>
</div>
<div class="SideTwo">
<h1>
Scrollable page
</h1>
<p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p>
</div>
</div>
</div>
Your issue is not with the sticky property but with the expectations you have of it. A sticky element is only sticky within its parent and so the Side One's height limits how far the menu can go.
You're going to have to put the Menu as a sibling to the "sides".
Alternatively you could divide Side One into two separate sides one for the menu and one for the rest, applying the position: sticky to the new side as it is the one who is supposed to cover its siblings while scrolling.

Chrome not stretching display:table elements in flex container

There are a lot of questions about vertical centering, the occasional flexbox-stretching oddity, or the difference between block and table elements, but I couldn't find anything about the (unexpected) behavior of this particular combination.
I'm in a bit of a tricky situation with the markup bootstrap-vue is giving me:
#navbar-container {
/* Given */
position: relative;
display: flex;
width: 100%;
}
#navbar {
/* Given */
flex-grow: 1;
display: flex;
flex-direction: row;
/* For illustration */
background-color: red;
}
.nav-item {
/* Given */
flex-grow: 1;
text-align: center;
/* Added to center .nav-link content vertically */
display: table;
/* Without this Chrome and Edge don't stretch to the height of #navbar(-container), but Firefox does */
/*height: 100%;*/
}
.nav-link {
/* Added to center content vertically */
display: table-cell;
vertical-align: middle;
/* Should cover #navbar's red background */
background-color: lightgreen;
}
<div id="navbar-container">
<div id="navbar">
<div id="brand">
<!-- Gives height to #navbar -->
<img src="https://via.placeholder.com/100">
</div>
<div class="nav-item">
<a class="nav-link">
Item 1
</a>
</div>
<div class="nav-item">
<a class="nav-link">
Item 2
</a>
</div>
<div class="nav-item">
<a class="nav-link">
Item 3
</a>
</div>
</div>
</div>
I'm trying to vertically center the content of .nav-link across the full height of #navbar.
Keep in mind that I can't change anything about the markup here, it's given to me by the framework.
Since #navbar (implicitly) has align-items: stretch, I would assume that .nav-item is stretched to the height of #navbar. Firefox agrees, but Chrome and Edge don't.
The interesting part is that this happens only with display: table elements.
Any other display value (correctly) stretches .nav-item to the height of #navbar.
Note that .nav-link doesn't automatically stretch along in that case, but that's to be expected.
Adding height: 100% to .nav-item fixes the problem, but I can't understand why this is necessary.
I'm not looking for alternative vertical-centering solutions, adding the height works fine.
Using nested flexbox or line-height poses other (architectural) issues.
I suppose at this point I'm mostly curious why this happens, and perhaps more importantly: which browser is in the wrong here?
Here you go with officlal doc.
Table elements have an internal 'table wrapper box'. This wrapper is stretched, but the actual table itself isn't stretched to that box. The table height only grows with its content, or when you specify a height.
It's unclear why, but Firefox apparently does stretch the actual table automatically.

CSS display:table content height

I am trying to make a number of columns the same height, and have decided to go down the display:table CSS route.
<div class="header" style="display: table; width: 100%; background-color: yellow">
<div class="title" style="font-size: 30px; display: table-cell;">Navigation Title</div>
<div class="navigation" style="display: table-cell;">
<a class="navigation-link" style="background-color: red">Home</a>
<a class="navigation-link">About</a>
<a class="navigation-link">Contact</a>
</div>
</div>
I would like the navigation-links to the the full height of the header table (so as to add background-color to them), but the navigation seems to have some padding automatically added to the top and bottom. How would i set the height of navigation, and navigation-links to be the height of the header table.
I have tried using height:100% in various places but that did not seem to work (I am probably missing something). Here is a diagram to show what i mean:
Try to play with display: inline-block;, vertical-align: top;, padding-top and height of your navigation links:
.navigation {
...
vertical-align: top;
}
.navigation-link {
...
display: inline-block;
height: 100%;
padding: 7px 5px;
}
Demo: http://jsfiddle.net/y8AF5/
This seems to solve your problem : DEMO
CSS
.navigation > a {
display:inline-block;
border:1px solid #CCC;
line-height:2.5em;
}
What you have done so far is styling the classes but no styling was done for a tag.
Now, the trick is to change the display type of a and using line-height to provide appropriate spacing of full height!!!

How to vertically align div in another div with text?

I'm trying to center a div vertically in a parent div, where text is present. Here's what I've got:
It looks a little funny because the text seems to be centered properly, but the yellow boxes aren't. This is how I'm doing it:
.btn {
background-color: #ccc;
color: #000;
width: 200px;
border: solid 1px black;
text-align: center;
vertical-align: middle;
display: table-cell;
}
.square {
background-color: #ff0;
width: 20px;
height: 20px;
display: inline-block;
}
.inner {
display: inline-block;
}
<div class="btn">
<div class="square"></div>
<div class="inner">Hello</div>
<div class="square"></div>
</div>
Should my usage of "table-cell" + vertical-align be working? I only care about html5, I'm really just targeting the latest versions of mobile safari, so don't have to worry about older browsers etc.
Here's a js fiddle of this:
http://jsfiddle.net/TrJqF/
Thanks
Set vertical-align:top on the square class. The extra space comes from space reserved for descendant text elements like j, g, y etc. that drop below the line.
jsFiddle example
Actually there is no difference between both the height. Apply yellow background color to inner class and see the difference in explicit and no height.
both square div doesn't have content and inner div have content. The css box aligning by itself based on its content. Add empty space to the square div as follows:
<div class="btn">
<div class="square"> </div>
<div class="inner">Hello</div>
<div class="square"> </div>
</div>
If you want you can add top and bottom margin 1 or 2 pixel which will show your expectation.

How to make <div> inline? All <div>, even when their total width more than width of their parent?

I need to make <div> displayed inline and hide them with "overflow: hidden" for their parent.
Width for <div> is set to 20% with "box-sizing" property, so they are exactly 20% of their parent width.
The usual method, using "float: left" doesn't help, because it makes only 5 <div> displayed in one line, and the rest of them shown in new line under the first 5 <div>.
How to make all <div> displayd inline and hide the rest of them if they are too wide to be shown inside of their parent, using "overflow: hidden"?
I have the following document structure:
<body>
<div class="column">
<div class="header">Some text</div>
<ul class="item_list">
<li class="simple">Some text<br></li>
<li class="simple">Some text<br></li>
<li class="simple">Some text<br></li>
...
</ul>
</div>
You can see what I mean here. But I've made it using javascript (setted for <div> "position: absolute" and generated "margin-left" for each elemet) and it causes great problems for future development.
DEMO: http://jsfiddle.net/marcuswhybrow/7YDfE/3/
Use display: inline-block and white-space: nowrap in combination:
<div class="wrapper">
<div class="inline"></div>
<div class="inline"></div>
<div class="inline"></div>
</div>
Then use the appropriate CSS:
div.wrapper {
width: 200px; /* or whatever */
overflow: hidden;
white-space: nowrap;
}
div.inline {
display: inline-block;
}
The demo contains a little jQuery animation to illustrate the effect:
DEMO: http://jsfiddle.net/marcuswhybrow/7YDfE/3/
If the div elements are display: inline then applying white-space: nowrap; to the parent element will prevent their wrapping to new lines.
Since you have a known number of divs, have you tried using absolute positioning instead of floats, and specifying left:20% left:40%, etc.?
If you set the container div's height to a fixed value, and give all the inner elements display: inline-block, this should do the trick. inline-block will make each element align to the left, but keep it's dimensions, while the fixed height container will hide any that overflow to a new line.
This will do what you want with the addition of removing the white space between while allowing nice code formatting. The container gets font-size:0px ftw.
Markup
<div class="wrapper">
<div class="inline">Some text </div>
<div class="inline">Some sample text </div>
<div class="inline">Some Other text </div>
</div>
CSS
div.wrapper {
width: 250px; /* or whatever */
overflow: hidden;
white-space: nowrap;
border: 1px solid red;
font-size:0px;
}
div.inline {
display: inline-block;
width: 80px;
height: 20px;
background-color: black;
color:white;
margin: 0; padding: 0;
border: 1px solid blue;
font-size:12px;
}

Resources