I am trying to create a responsive navigation bar, similar to the one on Stack Overflow. I have attached an image of the layout I'm trying to achieve.
For simplicity, I added some values to make it easier to follow. There is the outer div that encapsulates the whole page, outer-wrapper and the main div that encapsulates the main content (navigation bar, main content, and footer), main-wrapper.
Now suppose that outer-wrapper is 1000px wide and main-wrapper is 800px wide, then there is 100px of buffer on the left and right side. When the window shrinks, I want the buffer to be used up before any of the main content changes.
CSS
.outer-wrapper {
width: 100%;
}
.main-wrapper {
width: 800px;
display: flex;
flex-direction: column;
margin-left: auto;
margin-right: auto;
position: relative;
}
.nav-home {
position: fixed;
top: -30px;
left: -30px;
height: 60px;
width: 100%;
padding: 20px 20px 0px 20px;
display: flex;
justify-content: space-around;
}
}
HTML
<div class='outer-wrapper'>
<div class='main-wrapper'>
<div class='nav-bar'>...</div>
<div class='main-content'>...</div>
<div class='footer'>...</div>
</div>
</div>
The problem is when the window shrinks to match the width of main-wrapper at 800px, there is still a left and right margin in the navigation bar. How would I ensure the width of the navigation bar matches the width of the main content and footer when the left and right margin is shrunk to 0?
Thanks.
I stripped out some of your styles from the .nav-bar class and it seems to be performing as you require - am I missing something?
I've added colours to help visualise the resizing.
.outer-wrapper {
background-color: yellow;
width: 100%;
}
.main-wrapper {
background-color: blue;
width: 800px;
display: flex;
flex-direction: column;
margin-left: auto;
margin-right: auto;
position: relative;
}
.nav-bar {
background-color: red;
justify-content: space-around;
}
.main-content {
background-color: green;
}
.footer {
background-color: purple;
}
<div class='outer-wrapper'>
<div class='main-wrapper'>
<div class='nav-bar'>Nav Bar</div>
<div class='main-content'>Main Content</div>
<div class='footer'>Footer</div>
</div>
</div>
.outer-wrapper {
width: 100%;
}
.main-wrapper {
width: 800px;
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
margin: 0 auto;
}
.main-wrapper > * {
padding: 10px;
flex: 1 100%;
}
.nav-bar {
background: tomato;
}
.footer {
background: lightgreen;
}
.main-content {
background: deepskyblue;
}
.aside-1 {
background: gold;
}
.aside-2 {
background: hotpink;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 0 0;
}
}
#media all and (min-width: 800px) {
.main-content {
flex: 3 0px;
}
.aside-1 {
order: 1;
}
.main-content {
order: 2;
}
.aside-2 {
order: 3;
}
.footer {
order: 4;
}
}
body {
padding: 2em;
}
<div class="outer-wrapper">
<div class="main-wrapper">
<nav class="nav-bar">Navbar</nav>
<main class="main-content">content</main>
<aside class="aside aside-1">aside 1</aside>
<aside class="aside aside-2">aside 2</aside>
<footer class="footer">footer</footer>
</div>
</div>
this is the code that I made, hopefully it will help you and what you expect
Related
I have setup the following layout. The content__item elements (which are commented below) are overflowing vertically outside main container.
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
height: 100%;
padding: 2rem;
}
.content__item {
flex: 1;
margin-left: 1rem;
background-color: white;
}
<div className="root">
<nav className="nav"></nav>
<main className="main">
<div className="menu"></div>
<div className="content">
<!-- Overflowing -->
<div className="content__item"></div>
<div className="content__item"></div>
<div className="content__item"></div>
</div>
</main>
</div>
I am pretty sure its a flexbox bug. I tried using min-height: 0 on the container but it still doesn't work. I setup an environment here for reference.
The reason the content_items are overflowing is because height: 100% causes problems with flex. However if you remove that, the elements don't appear to fill the available height. This is because their parent (the content div) is not the child of a flex element, so it is in fact this element and not the content__item that isn't taking up the available height.
We can fix this by adding display:flex to the main div (the parent of content)... however now we have another problem! This makes the other child of content (the nav element) appears to the side. To fix this, we can use flex-direction: column;
The main changes you need to make this work as as follows:
.main {
flex-grow: 1; /* you already have this to allow the children grow */
display: flex; /* Add this so the content element can use the full height */
flex-direction: column; /* Add this to make the children stack one below another */
}
.content {
display: flex; /* you already had this */
flex:1; /* Add this to make it take up the available height */
}
.content__item {
flex: 1; /* You don't actually need this now */
}
Working Example:
Also FYI, you need to set the body margin to 0 - otherwise the 100vh extends larger than the screen as it is getting added to the default margin.
body { margin:0; }
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
display:flex;
flex-direction:column;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
padding: 2rem;
flex:1;
}
.content__item {
margin-left: 1rem;
background-color: white;
}
<div class="root">
<nav class="nav"></nav>
<main class="main">
<div class="menu"></div>
<div class="content">
<!-- Overflowing -->
<div class="content__item">some text here</div>
<div class="content__item">some text here</div>
<div class="content__item">some text here</div>
</div>
</main>
</div>
body, html {
margin: 0;
}
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
display: flex;
flex-direction: column;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
padding: 2rem;
flex: 1;
}
.content__item {
flex: 1;
margin-left: 1rem;
background-color: white;
}
<div class="root">
<nav class="nav"></nav>
<main class="main">
<div class="menu"></div>
<div class="content">
<!-- Overflowing -->
<div class="content__item">a</div>
<div class="content__item">b</div>
<div class="content__item">c</div>
</div>
</main>
</div>
I'm trying to create an element that will hold various images that should be responsive (width AND height). So far using flexbox has been successful except for one thing. Every time I reduce the width of my window, at a certain point, the flex items overflow the parent container and spill out beyond the containers width.
nav {
position: fixed;
top: 0;
left: 0;
height: 80px;
line-height: 80px;
background: black;
color: #fff;
width: 100%;
text-align: center;
}
body, p {
margin: 0;
padding: 0;
width: 100vw;
}
.wrapper {
height: 100vh;
margin: 100px auto;
min-width: 0;
}
.flex {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
max-width: 100%;
min-width: 200px;
flex-wrap: nowrap;
}
img {
max-height: 100%;
max-width: 100%;
}
.txt-rt {
text-align: right;
}
.footer {
background: darkgray;
height: 300px;
text-align: center;
}
<nav>This is a Navbar</nav>
<div class="wrapper">
<div class="flex">
<p>hello</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg" alt="">
<p class="txt-rt">world</p>
</div>
</div>
<div class="footer">
<h3 class="footer">Footer content</h3>
</div>
In this CodePen example, each time the window width is <560px or so and the height is at least 600px, the image is no longer responsive in width and the content overflows outside the screen.
All the other functionality looks like it's working as expected, but once I reduce my window width to a certain point the image will not shrink down. This prevents all 3 flex items being viewable in the width of the screen. Is there code I should be adding - not media queries since various sizes of images will be used - to make sure the image is responsive no matter the size of the window? Note: I don't want the items to wrap down to a second line.
You can use this code
* {
box-sizing: border-box;
}
body {
display: flex;
min-height: 100vh;
flex-direction: column;
margin: 0;
text-align: center;
}
#main {
display: flex;
flex: 1;
flex-direction: column;
}
#main>article {
flex: 1;
text-align: center;
}
#main>nav,
#main>aside {
background: beige;
}
#main>nav {
order: -1;
}
header,
footer {
background: yellowgreen;
height: 20vh;
}
header,
footer,
article,
nav,
aside {
padding: 1em;
}
#media screen and (min-width: 576px) {
#main {
flex-direction: row;
}
#main>nav,
#main>aside {
flex: 0 0 20vw;
}
}
<header>This is a Navbar</header>
<div id="main">
<article><img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg" alt=""></article>
<nav>hello</nav>
<aside>world</aside>
</div>
<footer>Footer content</footer>
.flex {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
max-width: 100%;
min-width: 200px;
flex-wrap: wrap; // this will move your content to new line if there is less space
}
How do I get the left sidebar to overlay the content instead of pushing the content? I want it overlay on mobile but push on web layout. Flexbox is a little new to me so not sure if I need a different layout to do this or if this is possible with flexbox? I'm guessing I need to remove the sidebar from the flexbox and use a fixed relative layout ??
I'm also using angular but I removed the angular code just for simplicity so don't mind the extra divs please.
<div class="wrapper">
<header class="header">
header
</header>
<div class="main">
<div class="left-sidebar">
left sidebar
</div>
<div class="main-content-wrapper">
<div class="main-content">
<h3>Main </h3>
</div>
<footer class="footer">
<p>content</p>
<p>content</p>
<p>content</p>
</footer>
</div>
</div>
</div>
body,
html {
height: 100%;
overflow: hidden;
}
header {
min-height: 60px;
flex: none;
width: 100%;
background-color: silver;
}
.wrapper {
height: 100vh;
display: flex;
flex-direction: column;
.main {
flex: 1;
display: flex;
.main-content-wrapper {
display: flex;
flex: 1;
flex-direction: column;
overflow: auto;
.main-content {
padding: 2rem;
flex: 1;
background-color: antiquewhite;
}
footer {
background-color: silver;
min-height: 300px;
flex-shrink: 0;
}
}
}
}
.left-sidebar {
width: 0;
height: 100%;
overflow: auto;
flex: none;
&.active {
width: 250px;
}
.left-sidebar-content {
padding: 1rem;
}
}
Try this, I actually made pretty much a new structure, although not that different to yours, (did remove some elements just to work with less code); I'm using flexbox to make the whole wrapper a flex container, as well as media queries to indicate when the sidebar should push the content to the side, and when to overlap the content along with an overlay.
document.getElementById('toggleBtn').onclick = function() {
document.getElementById('sidebar').classList.toggle('active');
document.getElementById('overlay').classList.toggle('hidden');
}
document.getElementById('overlay').onclick = function() {
document.getElementById('overlay').classList.toggle('hidden');
document.getElementById('sidebar').classList.toggle('active');
}
body {
margin: 0;
}
.wrapper {
display: flex;
align-items: stretch;
height: 100vh;
}
.main-content-wrapper {
width: 100%;
}
#sidebar {
min-width: 230px;
max-width: 230px;
background-color: lightgray;
transition: all 0.3s;
height: 100vh;
margin-left: -230px;
/* top layer */
z-index: 3
}
#sidebar.active {
margin-left: 0px;
}
#media (max-width: 580px) {
#sidebar {
position: fixed;
top: 0;
/* top layer */
z-index: 3
}
.overlay {
background-color: rgba(0, 0, 0, 0.425);
width: 100vw;
height: 100vh;
z-index: 2;
top: 0;
left: 0;
position: absolute;
}
.overlay.hidden {
display: none;
}
}
<div class="wrapper">
<div class="left-sidebar" id="sidebar">
left sidebar
</div>
<div class="main-content-wrapper">
<div class="main-content">
<h3>Main </h3>
<button type="button" id="toggleBtn">Toggle</button>
</div>
</div>
<div class="overlay hidden" id="overlay"></div>
</div>
So I have HTML that CANNOT be changed whatsoever and I have a certain design that I'm aiming for. And I cannot use JS for this yet.
Just a note too, the container is actually the parent of all the other elements on the screen. However, the reason I drew like that is because that's the look i want, and if possible, as I scroll down the only thing that scrolls is element 3 and 4, and 3 and 1 stay fixed. At the moment the container is a flex box. The CSS that I have doesn't really do what I need it to do, but here it is:
html,
body {
min-height: 100%;
height: 100%;
}
#container {
display: flex;
flex-wrap: wrap;
height: 100%;
}
#intro {
background-color: yellow;
width: 20%;
order: 2;
}
#nav {
background-color: red;
width: 15%;
order: 1;
}
#content {
background-color: blue;
width: 65%;
order: 3
}
article {
order: 4;
}
footer {
background-color: magenta;
}
<div id="container">
<section id="intro">...</section>
<div id="content">...</div>
<aside id="nav">...</aside>
<article>
<li><img src="http://via.placeholder.com/100x100"></li>
<li><img src="http://via.placeholder.com/100x100"></li>
</article>
</div>
<footer>...</footer>
as I scroll down the only thing that scrolls is element 3 and 4
Using position: fixed we can make nav/intro/footer stay while content/article scroll.
The align-items: flex-end; on content/article will keep them right aligned, and flex-grow: 1 on container/content will make them fill the remaining space.
Stack snippet
html {
display: flex; /* IE min-height bug fix */
}
body {
width: 100%; /* using IE bug fix it need a width */
display: flex;
flex-direction: column;
min-height: 100vh; /* instead using precent all over */
margin: 0;
}
#container {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: flex-end;
}
#nav {
position: fixed;
left: 0;
top: 0;
width: 15%;
height: calc(100% - 30px); /* make up for footer */
background-color: red;
}
#intro {
position: fixed;
left: 15%;
top: 0;
width: 20%;
height: calc(100% - 30px); /* make up for footer */
background-color: yellow;
}
#content {
background-color: lightblue;
width: 65%;
flex-grow: 1;
}
article {
margin-bottom: 30px; /* make up for footer */
}
article li {
list-style: none;
}
footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 30px;
background-color: magenta;
}
<div id="container">
<section id="intro">Intro</section>
<div id="content">
Content along with below article that will scroll and leave "Nav"/"Intro" fixed. <br>
Content along with below article that will scroll and leave "Nav"/"Intro" fixed. <br>
</div>
<aside id="nav">Nav</aside>
<article>
<li><img src="http://via.placeholder.com/100x100"></li>
<li><img src="http://via.placeholder.com/100x100"></li>
</article>
</div>
<footer>Footer</footer>
You are almost there.
Just set the article to have the same width as the #content and set the
justify-content:flex-end on the #container.
#container {
display: flex;
flex-wrap: wrap;
height: 100%;
justify-content: flex-end;
}
article {
order: 4;
width:65%;
}
html,
body {
min-height: 100%;
height: 100%;
}
#container {
display: flex;
flex-wrap: wrap;
height: 100%;
justify-content: flex-end;
}
#intro {
background-color: yellow;
width: 20%;
order: 2;
}
#nav {
background-color: red;
width: 15%;
order: 1;
}
#content {
background-color: blue;
width: 65%;
order: 3
}
article {
order: 4;
width: 65%;
background: cyan;
}
footer {
background-color: magenta;
}
<div id="container">
<section id="intro">...</section>
<div id="content">...</div>
<aside id="nav">...</aside>
<article>
<li><img src="http://via.placeholder.com/100x100"></li>
<li><img src="http://via.placeholder.com/100x100"></li>
</article>
</div>
<footer>...</footer>
I am using the flexbox to lay out a web app. It works, except for the main content area. The "router-view" is the expected full height. But the div inside of this is NOT full height of the router-view?
How do I make the div with id of "make-full-height" full height?
I have tried setting the height to 100%, but this has no effect.
html
<div class="full-screen flex-container-column">
<div class="header no-flex">
Fixed Header
</div>
<!--The router-view IS full height-->
<router-view class="flexible">
<div id="make-full-height">
How do I make this div full height?
</div>
</router-view>
<div class="footer no-flex">
Fixed Footer
</div>
</div>
css
.full-screen {
height: 100vh;
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.no-flex {
flex: 0 0 auto;
overflow: auto;
}
.footer {
height: 30px;
background: #555;
color: white;
}
.header{
height: 50px;
background: #555;
color: white;
}
.flex-container {
flex: 1 1 auto;
display: flex;
overflow: hidden;
}
.left, .right {
width: 200px;
background: #eee;
}
.flexible {
flex: 1 1 auto;
}
Set the <router-view to have display: flex, and set flex:1 for the #make-full-height. This way #make-full-height will fill it's container since there are no other children.
.full-screen {
height: 100vh;
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.no-flex {
flex: 0 0 auto;
overflow: auto;
}
.footer {
height: 30px;
background: #555;
color: white;
}
.header{
height: 50px;
background: #555;
color: white;
}
.flex-container {
flex: 1 1 auto;
display: flex;
overflow: hidden;
}
.left, .right {
width: 200px;
background: #eee;
}
.flexible {
flex: 1 1 auto;
background-color: #88F;
display: flex;
}
#make-full-height {
flex : 1;
background-color: #8F8;
}
<div class="full-screen flex-container-column">
<div class="header no-flex">
Fixed Header
</div>
<!--The router-view IS full height-->
<router-view class="flexible">
<div id="make-full-height">
How do I make this div full height?
</div>
</router-view>
<div class="footer no-flex">
Fixed Footer
</div>
</div>