Having an issue with div layout positioning - html

I have been fighting with this for a while, I'm trying to make a specific setup and I've gotten so frustrated at it I've resorted to using tables (very bad). So what I'm trying to do:
5 divs.
1 on the right side of the screen, ~120px width, 100% of the page
height
1 in the bottom left of the page, 120px height, 120px width
1 above that one, 120 width, all remaining height
in the middle between these 1 div on the top, with height of 80px,
and width filling between the other divs
and the last div in the middle taking up all remaining space
Any solution I have come up with required at least some JS, which I am doing everything I can to avoid, so I am looking for a purely CSS3 solution!

You could do it using HTML5 and CSS3 using display flex
Something I quickly mocked up http://codepen.io/tom-maton/pen/mbJAs
HTML:
<div class="main">
<div class="left">
<div class="top-left-column">Top left</div>
<div class="bottom-left-column"> bottom left</div>
</div>
<div class="center">
<div class="center-top-column">Top Center</div>
<div class="center-bottom-column">Bottom center</div>
</div>
<div class="right">
<div class="right-column">Right Column</div>
</div>
</div>
CSS:
div {
border: 1px solid #333;
}
.main {
border: 0;
display: flex;
flex-direction: row;
height: 100vh;
}
.top-left-column {
height: calc(100vh - 120px);
width: 120px;
}
.bottom-left-column {
height: 120px;
width: 120px;
}
.center {
display: flex;
align-content: stretch;
flex-direction: column;
flex: 1 1 0;
}
.center-top-column {
height: 80px;
}
.center-bottom-column {
height: calc(100vh - 80px);
}
.right-column {
height: 100vh;
width: 120px;
}
You just need to check your browser support beforehand as flex not supported in IE8/9

Related

Scroll Flexbox dashboard problem CSS HTML

When creating my dashboard with flexbox css html, I have a scroll problem for example:
In the middle red container if I make it vertical the horizontal one does not work well for me opteniendo results like it expands the container descuadrando the design.
If I work the horizontal scroll does not work the vertical scroll expanding this.
I want it to work like this in the following image:
Desired result
I have tried many things with the flexbox like setting the height or width to 100% and even forcing the scroll, but I can't get the expected effect.
Your question is a bit broad, you should post your current solution next time to see which part is not working. For example, I couldn't really tell if the vertical scrollbar in the middle region is supposed to scroll the top or the middle part. Anyways, if you're set on using flexboxes, here's a way to do it:
body {
margin: 0;
}
main {
display: flex;
width: 100vw;
height: 100vh;
}
.left {
width: 20%;
background-color: cornflowerblue;
}
.left__header {
background-color: lightblue;
}
.middle {
display: flex;
flex-direction: column;
width: 40%;
background-color: salmon;
}
.middle__header {
flex-shrink: 0;
overflow-y: auto;
background-color: lightpink;
}
.middle__body {
overflow-x: auto;
}
.middle__footer {
margin-top: auto;
background-color: white;
}
.right {
width: 40%;
background-color: lightgreen;
}
<main>
<div class="left">
<div class="left__header">1</div>
<div class="left__body"></div>
</div>
<div class="middle">
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
</div>
<div class="right">
SideBar Right
</div>
</main>
But if you don't plan on dynamically adding/removing elements or moving stuff around in the base layout (i.e. these regions stay the same during the use of the application) I'd recommend using CSS grid instead:
body {
margin: 0;
}
main {
display: grid;
grid-template:
"left-header middle-header right" min-content
"left-body middle-body right"
"left-body middle-footer right" min-content / 2fr 4fr 4fr;
width: 100vw;
height: 100vh;
}
.left__header {
grid-area: left-header;
background-color: lightblue;
}
.left__body {
grid-area: left-body;
background-color: cornflowerblue;
}
.middle__header {
grid-area: middle-header;
overflow-x: auto;
background-color: lightpink;
}
.middle__body {
grid-area: middle-body;
overflow-y: auto;
background-color: salmon;
}
.middle__footer {
grid-area: middle-footer;
background-color: white;
}
.right {
grid-area: right;
background-color: lightgreen;
}
<main>
<div class="left__header">1</div>
<div class="left__body"></div>
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
<div class="right">
SideBar right
</div>
</main>
This results in the same output, but the HTML/CSS is much more readable IMO. It uses the grid-template property, which is fairly new, but should be available in most browsers.

Organize items within a container like flex-direction: column with 3 columns but unknown height

So, I hope I get this right. Here is the jsfiddle I came up with so far https://jsfiddle.net/fymo97zn/7/
So, I have a .page element that has fixed height and width to fit on a A4 page.
Within this are 2 containers one .units has width 100% and a dynamic (unknown) height.
The second container contains multiple (1...n) .upgrade elements.
Now, I want to fill those unit elements in a 3 column ways but not from left to right but form top to bottom, like a newspaper, or just like column-count: 3 would do, but filling the first column first.
The issue seems to be, that it does not know how to wrap because I don't know the height of .units and this not the available space for .upgrades.
Does anyone have an idea?
I'm working with nuxt and scss.
.page {
max-height: 400px;
max-width: 400px;
min-height: 400px;
min-width: 400px;
background-color: lime;
}
.units {
height: 100px;
width: 400px;
background-color: red;
}
.rest {
background-color: blue;
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 250px;
width: 100%;
overflow: hidden;
}
.upgrade {
background-color: orange;
width: 28%;
height: 50px;
padding: 5px;
margin: 5px;
}
<div class="page">
<div class="units">
</div>
<div class="rest">
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
<div class="upgrade"></div>
</div>
</div>

Responsive CSS Image size effects row sizes

I know this sounds like it's been asked before but I've played around with a lot of techniques I've found from other questions and nothing seems to get the desired effect I need.
I'm trying to make something that will be responsive like this:
Responsive Example gif
I basically need an image to be centered, where the image is at 100% size.
Here is what I tried to get this effect:
I first made a div containing three child divs for "columns". Then inside the center column I made three child divs for "rows". Now I need the image to fill the max width it's allowed while still maintain that square aspect ratio. As well the height of the image should determine the height of the top and bottom rows.
Then it should just be a matter of having the text inside the top and bottom row align to the bottom and top of their divs respectively.
This would look something like this:
HTML Visualization of columns
HTML Visualization of center rows
The issue I'm running into is I can't seem to get the center image to determine the heights of the rows above and below it.
I've tried...
Flexbox
using vh (view height)
and a bit of using calc() but to no luck
Setting aspect ration with padding-top: 100%
What the code looks like
/* .row & .col from materialize.css */
.full {
height: 100vh;
}
.art_top {
height: 10vh;
/* I Don't actually want this fixed though */
padding-bottom: 10px;
display: flex;
}
.art_center {
height: 80vh;
/* I Don't actually want this fixed though */
}
.art_bottom {
height: 10vh;
/* I Don't actually want this fixed though */
padding-top: 10px;
display: flex;
}
#cover_art {
width: 100%;
height: 100%;
background: center / cover no-repeat;
}
#song_name {
align-self: flex-end;
}
#artist_name {
align-self: flex-start;
}
<div class="row">
<div class="col s2 m3 full"></div>
<div class="col s8 m6 full">
<div class="row art_top">
<a id="song_name" class="bold-title"></a>
</div>
<div class="row art_center">
<div id="cover_art"></div>
</div>
<div class="row art_bottom">
<a id="artist_name" class="bold-title"></a>
</div>
</div>
<div class="col s2 m3 full"></div>
</div>
Flexbox makes this kind of layout very straightforward. The trick is selectively allowing items to flex or shrink.
The flex property shorthand takes 3 values for flex-grow, flex-shrink, and flex-basis (the initial width or height depending on flex direction). Just keep clear which divs are serving as flex containers as you get into the details in the layout. It is very common to have divs that are both flex containers and flex items themselves too.
I also recommend using an img element instead of applying the image as a background so you dont have trouble with the aspect ratio in responsive window sizes.
A very nice resource: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
/* .row & .col from materialize.css */
body {
margin: 0;
}
.full {
height: 100vh;
}
.row {
display: flex;
}
.column {
flex: 1 1 auto;
}
.column2 {
background: #b4c2cf;
display: flex;
flex-direction: column;
}
.column1 {
background: #cbb3cc;
}
.column3 {
background: #cbb2b2;
display: flex;
align-items: center;
justify-content: center;
}
.art_top {
flex: 1 0 10vh;
display: flex;
justify-content: flex-start
align-self: flex-end;
}
.art_center {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: center;
}
.art_bottom {
flex: 1 0 10vh;
text-align: right;
}
#cover_art {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
#song_name {
align-self: flex-end;
}
#artist_name {
align-self: flex-start;
}
.bold-title {
display: block;
font-weight: bold;
padding: 10px;
}
.small-box {
background: #8f588c;
height: 100%;
max-height: 70px;
width: 100%;
max-width: 70px;
}
<div class="row full">
<div class="column column1"></div>
<div class="column column2">
<div class="art_top">
<a id="song_name" class="bold-title">My Album Title</a>
</div>
<div class="art_center">
<img id="cover_art" src="https://picsum.photos/400" />
</div>
<div class="art_bottom">
<a id="artist_name" class="bold-title">Artist Name</a>
</div>
</div>
<div class="column column3">
<div class="small-box"></div>
</div>
</div>

How to align 3 divisions in a row such that the last element is at the middle of the page?

How can I align 3 divs in a row, equally spaced, such that the last (rightmost) element is at the center of the page?
I think this is what you are looking for https://jsfiddle.net/o8z6exn5/2/
Set the wrapper to 50vw then display: flex; and justify-content: space-between; to equally space elements on left side of screen.
HTML
<div class="wrapper">
<div class="align">
</div>
<div class="align">
</div>
<div class="align">
</div>
</div>
CSS
.wrapper {
display: flex;
justify-content: space-between;
width: 50vw;
}
.align {
height: 10px;
width: 10px;
background-color: red;
}
The way I understood your question is that the rightmost div is supposed to be in the center of the page. In other words, the center of that div should match the center of the screen.
To do that we need a wrapper that is 50 % of the width of the screen + 50 % of the width of the rightmost div. For example, if the width of the screen is 1000px and the width of the div is 50px, the wrapper should then be 500px + 25px = 525px in width.
Equation above can be written in CSS like so width: calc(50vw + (var(--div-width) / 2));
Below is a snippet to a working solution. In case you wanted to make it so that the right edge of the rightmost div is in the center of the screen you simply need to make .wrapper have the width of 50vw.
:root {
--div-width: 50px;
}
.wrapper {
width: calc(50vw + (var(--div-width) / 2));
display: flex;
justify-content: space-between;
}
.item {
background-color: red;
height: 50px;
width: var(--div-width);
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

achieving equal height columns with flexbox

I am trying to build a layout which has two separate content groups: one on the left side and right side, with fixed width (20%/80%) for now. On each side, I am trying to arrange contents by using flexbox: left panel with flex-direction: column and right panel with flex-direction: row wrap. The number of contents on each side can be flexible. The panel with less contents should match the height of the other, 'taller' side.
So far, I was able to achieve the basic layout, as shown in this jsfiddle. However, my problem is that I cannot make the the 'shorter' panel to fill the height, even though I set the height to be 100%. In the given example, there is an empty space between 'C' div of left panel and 'Box7' div of the right panel. The html/css code is show below.
How could I fix this problem or is there nicer simpler layout solutions? Any help would be appreciated.
HTML
<div class='top'>
<div class='left'>
<div class='litem'>A</div>
<div class='litem'>B</div>
<div class='litem'>C</div>
</div>
<div class='right'>
<div class='ritem'>Box 1</div>
<div class='ritem'>Box 2</div>
<div class='ritem'>Box 3</div>
<div class='ritem'>Box 4</div>
<div class='ritem'>Box 5</div>
<div class='ritem'>Box 6</div>
<div class='ritem'>Box 7</div>
</div>
</div>
CSS
* { outline: 1px solid Grey; }
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: Cornsilk;
}
.top {
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
}
.left {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
width: 20%;
height: 100%;
}
.right {
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 80%;
height: 100%;
}
.litem, .ritem {
margin: 0;
padding: 0;
}
.litem { height: 50%; }
.ritem { height: 50%; width: 33.3%;}
.litem:nth-child(1) { background-color: Cyan; }
.litem:nth-child(2) { background-color: DarkCyan; }
.litem:nth-child(3) { background-color: DarkSeaGreen; }
When you apply height: 100% to html and body, you limit the growth of the child elements to 100% of the screen.
In your code, your .left flex item is indeed stretching to height: 100%, as specified. Add a border around .left for an illustration: DEMO
If you remove all the fixed heights, you'll enable the flex container to stretch all flex items, per the default setting: align-items: stretch (the setting that creates equal height columns). DEMO
When you add flex: 1 to the .left flex items (.litem), they then distribute all available space in the container evenly among themselves. DEMO.
In a nutshell, when you use the height property you override align-items: stretch, the flex setting for equal height columns.