Move sidebar in between other elements on smaller screens - html

I'm not totally sure this is possible, but I figured I'd ask.
I'm wondering to move a sidebar in-between some content when it hits a breakpoint.
So, for example something like this:
+---------------------+ +-------------+
| | | |
| Top Content | | |
| | | Sidebar |
| | | |
+---------------------+ | |
+---------------------+ | |
| | | |
| | | |
| | | |
| Other | | |
| Content | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
+---------------------+ +-------------+
To this:
+-------------------------+
| |
| Top Content |
| |
+-------------------------+
+-------------------------+
| |
| |
| Sidebar |
| |
| |
| |
+-------------------------+
+-------------------------+
| |
| |
| |
| |
| Other |
| Content |
| |
| |
| |
| |
+-------------------------+
So I know that I can set the orders, but I'm not quite sure how to get the "flow" to correctly set.
I'm wondering something like this:
.flex-container {
display: flex;
flex-direction: row;
}
.top-content {
order: 1;
}
.sidebar {
order: 3;
justify-self: flex-end;
}
.other-content {
order: 2;
}
#media screen and (max-width: 767px) {
.flex-container {
flex-direction: column;
}
.sidebar {
order: 2;
}
.other-content {
order: 3;
}
}
<div class="flex-container">
<div class="top-content">
...
</div>
<div class="sidebar">
...
</div>
<div class="other-content">
...
</div>
</div>
But I'm not sure if that's even plausible? Wondering if this is something that needs to be done with CSS Grid instead? Anyways, just a thought. Was hoping to use the same content structure without having to hide/show the same thing with breakpoints and writing more markup on the page.

It's simpler and easier with CSS Grid.
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 3fr;
grid-gap: .5em;
height: 100vh;
background-color: gray;
}
.top-content {
grid-column: 1;
background-color: orangered;
border: 1px dashed black;
}
.sidebar {
grid-column: 2;
grid-row: 1 / -1;
background-color: aqua;
border: 1px solid black;
}
.other-content {
grid-column: 1;
background-color: lightgreen;
border: 1px dashed black;
}
body {
margin: 0;
}
#media (max-width: 500px) {
.grid-container {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
.sidebar {
grid-column: 1;
grid-row: 2;
}
}
<div class="grid-container">
<div class="top-content">top content</div>
<div class="sidebar">sidebar</div>
<div class="other-content">other content</div>
</div>
jsFiddle demo

Well, I figured out how to achieve this, see:
.flex-container {
display:flex;
flex-flow: row wrap;
box-sizing: border-box;
}
#media screen and (max-width: 600px) {
break {display:none;}
}
div {
border: 1px black solid;
}
.flex-container > div {
box-sizing: border-box;
}
.flex-container > div, break{
display: inline-block;
}
break{
flex-basis: 100%;
width: 0px;
height: 0px;
overflow: hidden;
}
<div class="flex-container">
<div class="top-content" style="width: 350px; height: 500px;">
...
</div>
<div class="sidebar" style="width: 350px; height: 500px;">
...
</div>
<break></break>
<div class="other-content" style="width: 350px; height: 500px;">
...
</div>
</div>
The only thing I did was creating a custom HTML5 tag called <break>. This tag creates a new line between the divs that you specify. So, if you media-query is reached (due to lower resolutions) you only need to hide it.
The original idea was taken from: https://codepen.io/hrgdavor/pen/waXEqz
EDIT:
I realized about the leaking rowspan behaviour on my example. So I decided to search and I found this, and I created this demo:
.flex-container {
display:flex;
flex-flow: row wrap;
box-sizing: border-box;
flex-direction: column;
flex-wrap: wrap;
height: 1000px;
}
#media screen and (min-width: 600px) {
.top-content, .other-content {flex: 0 0 50%;}
.sidebar {flex: 0 0 100%; order: 1;}
}
#media screen and (max-width: 600px) {
.flex-container {flex-direction: row;}
.top-content, .other-content, .sidebar {flex: 0 0 100%;}
.other-content {order:2;}
}
.flex-container > div {
box-sizing: border-box;
}
/* Only for doing example */
.flex-container > div {
border: 1px black solid;
}
<div class="flex-container">
<div class="top-content">
...
</div>
<div class="sidebar">
...
</div>
<div class="other-content">
...
</div>
</div>
Note: box-sizing: border-box; is important.
Hope this helps!

Related

How to float an element to the right in flexbox with multiple flex items

Let's say I have a flexbox set up like this:
<div class="flexbox">
<div id="item-1"></div>
<div id="item-2"></div>
<div id="item-3"></div>
</div>
I currently have the flex items set up using CSS like so:
-------------------------------------------------
| 1 | 2 | 3 |
-------------------------------------------------
I want the items to change to this layout when the screen reaches a certain size:
--------------------
| 3 | 1 |
-----------------------------
| 2 |
-----------------------------
I know I can use #item-3 {order:-1} to move it to the beginning, but the part I'm having trouble with is floating element 1 to the right, above 2.
Any help is appreciated, thanks!
min-width is solution:
.flexbox {
display: flex;
flex-wrap: wrap;
}
.flexbox div {
border: 1px solid #ddd;
padding: 10px;
box-sizing: border-box;
}
#item-1, #item-3 {flex: 1;}
#item-2 {flex: 2;}
#media(max-width: 768px) {
#item-1, #item-3 {
order: 1;
}
#item-2 {
order: 2;
border-top: 0;
min-width: 100%;
}
}
<div class="flexbox">
<div id="item-1"></div>
<div id="item-2"></div>
<div id="item-3"></div>
</div>

How to have header and footer inside of container?

I need the appropriate Html and CSS for the following
Here is the layout of the app
Detailed Figure General Figure
------------------------- -------------------------
| App Header | | App Header |
------------------------- -------------------------
| Module Header| Sub | | | |
|--------------| Module | | | |
| |--------| | | |
| Module | Sub | | Main | Sub |
| Content | Module | | Module | Module |
| |--------| | Space | Space |
| | Sub | | | |
|--------------| Module | | | |
| Module |--------| | | |
| Footer | | | | |
------------------------- -------------------------
App Header is a static 60px
Module Header is a static 35px
Module Content is dynamic and overflows
Module Footer is dynamic and needs to always display everything on screen (it would never be more than say 500px)
What is the appropriate way to setup the Main Module Space and children?
How do I get the Headers and Footers to understand they're in containers and should not cover the entire width of the screen?
(I've used absolute position for the footer but that causes Module Content to hide behind the Module Footer)
I figured it out for the most part
https://jsfiddle.net/jackyFrosty/46mjtghv/47/
<div class='mainApp'>
<div class='appHeader'>
Header
</div>
<div class='contentContainer'>
<div class='leftContainer'>
<div class='moduleContainer'>
<header class='header'>
Header
</header>
<main class='content'>
<div>Content 1</div><div>Content 2</div><div>Content 3</div><div>Content 4</div>
<div>Content</div><div>Content</div><div>Content</div><div>Content</div><div>Content</div>
<div>Content</div><div>Content</div><div>Content</div><div>Content</div><div>Content</div>
<div>Content</div><div>Content</div><div>Content</div><div>Content</div><div>Content</div>
<div>Content 96</div><div>Content 97</div><div>Content 98</div><div>Content 99</div>
</main>
<footer class='footer'>
<div>Footer</div><div>Footer</div><div>Footer</div><div>Footer</div>
<!--div>Footer</div><div>Footer</div><div>Footer</div><div>Footer</div-->
</footer>
</div>
</div>
<div class='rightContainer'>
Right Content
</div>
</div>
</div>
* {
box-sizing: border-box;
border-style: solid;
border-color: white;
padding: 0px;
margin: 0px;
}
.mainApp {
height: 100%;
}
.appHeader {
height: 60px;
border-color: black;
}
.contentContainer {
height: calc(100vh - 60px);
}
.leftContainer {
float: left;
width: 75%;
height: 100%;
overflow: auto;
border-color: black;
}
.rightContainer {
float: left;
width: 25%;
height: 100%;
overflow: auto;
border-color: black;
}
/* /////////// Important part ////////// */
.moduleContainer {
border-color: orange;
display: -webkit-flex;
display: flex;
flex-direction: column;
height: calc(100vh - 60px);
}
.header {
border-color: red;
height: 35px;
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
}
.content {
border-color: green;
overflow-y: scroll;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
}
.footer {
border-color: blue;
}

Can flexbox sidebars share a new row?

Can I get flexbox sidebars to share a new row, after a media query?
Before (on wide screens)
+---+-------+---+
| | | |
| L | Main | R |
| | | |
+---+-------+---+
After (on narrow screens)
+-------+
| |
| Main |
| |
+-------+
| | |
| L | R |
| | |
+-------+
HTML (not changeable after media query)
<div class="container">
<div class="sideLeft">L</div>
<div class="MainContent">Main</div>
<div class="sideRight">R</div>
</div>
You can change order: -1 on main div with media queries. You also need to set flex-wrap: wrap on container element. Also calc(% - 10px) is for margin of 5px on both sides but if you don't want margins you can just use % as you can se here
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
height: 200px;
border: 1px solid gray;
padding: 5px
}
.container > div {
display: flex;
border: 1px solid black;
margin: 5px;
flex: 1;
}
div.main {
flex: 3;
}
#media(max-width: 480px) {
div.main {
order: -1;
flex: 0 0 calc(100% - 10px);
}
.container > div:not(.main) {
flex: 0 0 calc(50% - 10px);
}
}
<div class="container">
<div class="sideLeft">L</div>
<div class="main">Main</div>
<div class="sideRight">R</div>
</div>

Content is pushed down by DIV

This is a question based on this question:
Twitter bootstrap 3 two columns full height
I have the same layout. But, when I try to put a DIV in the content part, it pushes the content of the sidebar down. Here's a Fiddle
<header>Header</header>
<div class="container">
<div class="row">
<div class="col-md-3 no-float">Navigation</div>
<div class="col-md-9 no-float"><div><div style="width=100%;height:55px;background:red"></div>Content</div></div>
</div>
CSS:
html,body,.container
{
height:100%;
}
.container
{
display:table;
width: 100%;
margin-top: -50px;
padding: 50px 0 0 0; /*set left/right padding according to needs*/
-moz-box-sizing: border-box;
box-sizing: border-box;
}
header
{
background: green;
height: 50px;
}
.row
{
height: 100%;
display: table-row;
}
.col-md-3.no-float, .col-md-9.no-float {
float: none; /* thanks baxabbit */
}
.col-md-3
{
display: table-cell;
background: pink;
}
.col-md-9
{
display: table-cell;
background: yellow;
float: none;
}
If you have other suggestions, I need to do the following layout using Bootstrap and Angular, keeping the idea of having full-height columns from the upper post:
+-------------------------------------------------+
| Header |
+------------+------------------------------------+
| Nav.Header | ContentHeader | < |
|------------|------------------------------------|
|Navigation | Content | T |
| | | E |
| | | X |
| | | T |
| | | |
| | | |
| | | |
+------------+------------------------------------+
Thank you

Center a <span> relative to container div, align another span with right-aligned text left of it

I'm trying to align a span element in the center of a container div, and have another span with right-aligned text aligned left of it:
+--------------------------------------------------------+
| <div> |
+----------------------+----------+ |
| <span> | <span> | |
| | | |
| | | |
| | | |
| right-aligned | centered | |
| | | |
| | | |
| | | |
| | | |
+----------------------+----------+ |
| |
+--------------------------------------------------------+
The contents of both spans are dynamically generated, so I'd like to avoid any absolute pixel widths if possible.
Any idea how to achieve this type of layout?
Here is the markup I eventually went with based on Persinj's answer:
HTML
<nav class="navbar">
<span class="nav-aside">Right-aligned: </span>
<span class="nav-menu">centered</span>
<span class="nav-aside"></span>
</nav>
CSS
nav.navbar {
display: flex;
}
span.nav-aside {
flex-grow: 1;
flex-basis: 0;
text-align: right;
}
span.nav-menu {
align-self: center;
text-align: center;
}
I left the vendor prefixes out of my markup since I have limited browser requirements, and I'm relying on autoprefixer to take care of that. Please see the accepted answer if you need them.
Flexbox design / layout
This can be sloved using flex:
Setting tree boxes:
Aside, center and a hidden one, will fill the required space.
Setting a flex-grow will make make them take up different parts of the page.
Setting flex-grow: 1; on each will make them take up equal space.
Setting one of them to flex-grow: 0.5; will give this part less space to grow.
Adding a wrapper with the flex property we can use align-items:center to make sure they stay in the center of the wrapper.
Fiddle
.wrapper {
height: 250px;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-wrap: nowrap;
flex-direction: row;
align-items: center;
text-align: center;
}
.center,
.aside,
.not-shown {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.center {
flex-grow: 0.5;
background-color: lightblue;
height: 50px;
}
.aside {
text-align: right;
background-color: 1;
background: lightgreen;
height: 50px;
}
.not-shown {
visibility: hidden;
flex-grow: 1.5;
height: 50px;
}
<div class="wrapper">
<div class="aside">
aside
</div>
<div class="center">
center
</div>
<div class="not-shown">
</div>
</div>
HTML:
<div class="wrapper">
<span class="span-left">right-aligned</span>
<span class="span-center">centered</span>
</div>
CSS:
.span-left, .span-center { display: inline-block; }
.span-left {
width: 40%;
text-align: right;
}
.span-center {
width: 20%;
text-align: center;
}
Alternatively, use display: block and float: left; on your spans (don't forget to clear after the wrapper).