HTML -> Fixed top, Flexible bottom with min-height and dynamic squared content - html

I'm really struggling to create css layout like this:
Top row: fixed size: Ex: 50px;
Content: the biggest square the current width can fit. So width = height for this one. It should respect the bottom row min-height.
Bottom row: take all remaining space available, and with min-height. Ex: 50px.
No scrollbar. The idea is to use the current screen the best way possible for any resolution. No javascript unless it's only possible with js.
Any ideas?
That's the best I've got so far:
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>
css
body {
margin: 0px;
}
.shell {
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.header {
background-color: #0000ff;
height: 50px;
}
.square {
width: 100%;
background-color: #dc143c;
}
.footer {
background-color: #00008b;
height: 100vh;
}

You can use padding to get the aspect ratio:
body {
margin: 0px;
}
.shell {
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.header {
background-color: blue;
height: 50px;
}
.square {
width: 100%;
padding-top: 100%;
background-color: green;
}
.footer {
background-color: red;
height: 100%;
}
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>
Reference here

I think your question was already solved here:
Make a div fill the height of the remaining screen space
Mixed with your try:
body {
margin: 0;
}
.box {
display: flex;
flex-flow: column;
background-color: #000000;
height: 100vh;
max-width: calc(100vh - 100px);
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
.box .row.header {
flex: 0 1 50px;
background-color: #0000ff;
}
.box .row.content {
flex: 1 1 auto;
width: 100%;
background-color: #dc143c;
}
.box .row.footer {
flex: 0 1 40px;
background-color: #00008b;
}
<div class="box">
<div class="row header">
</div>
<div class="row content">
</div>
<div class="row footer">
</div>
</div>
Fiddle: https://jsfiddle.net/901s2kdL/

Content: the biggest square the current width can fit. So width =
height for this one. It should respect the bottom row min-height.
If you want the biggest square, the footer height will be fixed and it will be equal to min-height always (and it should be), so it doesn't matter if you will set it's height to 100% or 50px. max-width of square determining really sizes. If you look at this max-width: calc(100vh - 100px), the - 100px part is the real remaining space including header and footer, so if the header height is set to 50px, the footer height is also 50px.
body {
margin: 0px;
}
.shell {
background-color: black;
}
.header {
height: 50px;
background-color: red;
}
.square {
max-width: calc(100vh - 100px);
margin: 0 auto;
background-color: green;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.footer {
height: 50px;
background-color: blue;
}
<div class="shell">
<div class="header"></div>
<div class="square"></div>
<div class="footer"></div>
</div>

Related

Making three divs fit perfectly in a parent div

I have been building websites for way too long not to know how to do this. I'm embarrassed to ask. But I must.
I want a way to make any number of child divs within a parent div automatically span to the full width of the parent div.
My criteria for this fix are:
All of the child divs must be the exact same width
The width of the children divs must be responsive/dynamic
I would prefer a fix that doesn't involve sitting there and testing different percentages to find the exact percent width to prevent one of the children being wrapped or hidden (IE "display: if-there-was-an-easy-fix" instead of "width: 29.468749%")
I would love it if the fix would work with fixed margins and dynamic margins (margin: 10px and margin: 5%)
I'm 99% sure I knew the answer to this like a year ago but my current job requires that I work almost exclusively in tables, so I've forgotten how to do anything that isn't clunky and semantically disgusting.
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: 29.468749%;
height: 200px;
display: inline-block;
margin: 0;
padding: 0;
border: none;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="three">
</div>
</div>
use display: flex on parent and flex: 1 on child elements to get flexbox
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
/*display:block;*/
display: flex;
}
.box {
/*width: 29.468749%;*/
/*display:inline-block;
/*margin:0;
padding:0;*/
flex: 1;
height: 200px;
border: none;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="three">
</div>
</div>
The first thing that you'll want to do is remove display: inline-block from the elements, and instead give them a float: left. From here you can get a 'default' full-width alignment by giving your elements a width of about 33.33% each. This would total 99.99%, which is 'close enough' to the full-width (unless you're on a screen of 10000px width). To ensure it's perfect though, you can use the CSS calc() property to ensure that it's exactly one third with width: calc(100% / 3).
This will work for regular elements, but your second box also has margin on it, which also factors into the width calculation in accordance with the box model. Because you're adding a 5% margin on both sides, , you'll want to subtract a total of 10% from the width calculation for this element. This can be done with width: calc((100% / 3) - (5% * 2)).
This gives you three equally wide elements, with one element having additional margins, as can be seen in the following:
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: calc(100% / 3);
height: 200px;
margin: 0;
padding: 0;
border: none;
float: left;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
width: calc((100% / 3) - (5% * 2));
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="one">
</div>
</div>
If you want to change the number of elements, you simply need to update the 3 in each of the width calculations to reflect the number of siblings. This can be made even easier with a CSS variable, meaning you only have to update the CSS in one place:
:root {
--columns: 3;
}
#wrap {
width: 100%;
max-width: 500px;
background-color: gray;
height: 200px;
display: block;
}
.box {
width: calc(100% / var(--columns));
height: 200px;
margin: 0;
padding: 0;
border: none;
float: left;
}
#one {
background-color: aliceblue;
}
#two {
margin: 0 5%;
width: calc((100% / var(--columns)) - (5% * 2));
background-color: wheat;
}
#three {
background-color: coral;
}
<div id="wrap">
<div class="box" id="one">
</div>
<div class="box" id="two">
</div>
<div class="box" id="one">
</div>
</div>

Make an element overlap others when viewport runs out of room

I have the blue square that will contain things adding up to 800px.
I want the red square to always be fully visible. That is when you narrow the viewport, the red square should overlap the blue square, and not disappear on the right like it does actually.
How can I achieve that?
.container {
display: flex;
}
div {
height: 80px;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
width: 400px;
background: red;
}
<div class="container">
<div class="should-be-overlapped"></div>
<div class="always-full-width"></div>
</div>
To accomplish that, there is mainly 2 ways.
Either add a wrapper around the blue (which I recommend).
Updated codepen
Stack snippet
.container {
position: relative;
display: flex;
}
div {
height: 80px;
}
.wrapper {
flex: 1;
overflow: hidden;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
flex: 0 0 400px;
background: red;
}
<div class="container">
<div class="wrapper">
<div class="should-be-overlapped">
</div>
</div>
<div class="always-full-width">
</div>
</div>
Or use position: absolute.
Updated codepen
.container {
display: flex;
position: relative;
overflow: hidden;
}
div {
height: 80px;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
position: absolute;
right: 0;
width: 400px;
background: red;
}
.<div class="container">
<div class="should-be-overlapped">
</div>
<div class="always-full-width">
</div>
</div>
I have the blue square that will contain things adding up to 800px.
Then you should do it with the flex: 0 1 800px, which will enable it to shrink:
.container {
display: flex;
}
div {
height: 80px;
}
.should-be-overlapped {
/*min-width: 800px;*/
flex: 0 1 800px; /* doesn't grow but shrinks, initial width set to 800px (this is also its "max-width") */
background: blue;
word-break: break-all; /* for longer unbreakable strings, just for demo */
}
.always-full-width {
/*width: 400px;*/
flex: 0 0 400px; /* since you're using flexbox, doesn't grow nor shrink, initial width set to 400px (fixed) */
background: red;
}
<div class="container">
<div class="should-be-overlapped">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div class="always-full-width"></div>
</div>

Horizontally centering two stacked divs, when one has a vertical scrollbar

Centering elements horizontally is easy using margin: 0 auto;
However, it doesn't work if there are two elements stacked in a column and one has a scrollbar and the other does not. In that case, the two horizontal centered elements aren't aligned anymore.
Question: Is there any way to align the two elements without using Javascript to adjust the margin of the first one?
JSFIDDLE DEMO
<head>
<style>
body {
margin: 0; height: 100vh;
}
.header {
height: 50px; background: red;
}
.content {
overflow-y: scroll; background: blue;
}
.inner {
background: rgba(255,255,255,.5); max-width: 300px;
margin: 0 auto; min-height: 50px;
}
.content > .inner {
min-height: 300px;
}
</style>
</head>
<body>
<div class="header">
<div class="inner"></div>
</div>
<div class="content">
<div class="inner"></div>
</div>
</body>
The main problem is obviously the centering. So why not circumvent it and use margin-left?
Try this CSS:
.inner { margin-left: calc(50vw - 150px); } /* half viewport width less half element width
(for precise centering) */
body {
margin: 0;
height: 100vh;
}
.header {
height: 50px;
background: red;
}
.content {
background: blue;
overflow-y: scroll;
}
.inner {
background: rgba(255,255,255,.5);
max-width: 300px;
/* margin: 0 auto; <-- remove */
margin-left: calc(50vw - 150px); /* new */
min-height: 50px;
}
.content > .inner {
min-height: 300px;
}
<div class="header">
<div class="inner"></div>
</div>
<div class="content">
<div class="inner"></div>
</div>
Revised Fiddle
Answer from Wes in chat:
This can be solved by adding a scrollbar to the first one, but hiding it from the user.
.header {
height: 50px;
background: red;
overflow-y: scroll;
width: 120%;
margin-left: -10%;
}
JSFIDDLE DEMO
If you're concerned a user could have a scrollbar wider than 10%, increase it width: 300% and margin-left: -100%. If somebody has a scrollbar as wide as the page, he / she can't use the page anyway.

Place content from top and centre align it in the wrapper div that has height and width 100%

I need to place the content one below the other from the top and center align it.
I tried making all the rows positioning them absolute and making the
top:20% ,top:40% ,top:60% respectively and margin: 0 auto does not work.So I had to put left percentages for all three rows.
It looks rubbish when I reduce width of browser and when I reduce the height of the browser the divs overlap each other
I do not want overflow:auto or overflow-y:scroll .I want the content to be placed in that 100% height of wrapper and centered perfectly.How to implement this and also suggest me how to do it in media queries ?
HTML
<div id="wrapper">
<div id="row1">Long Text</div>
<div id="row2">Long Text</div>
<div id="row3">Long Text</div>
</div>
CSS
html,body{
height: 100%;
width: 100%;
}
#wrapper{
height: 100%;
width: 100%;
}
#row1{
height: 200px;
width: 600px;
}
#row2{
height: 400px;
width: 800px;
}
#row3{
height: 200px;
width: 500px;
}
Please do like this
html,body{
height: 100%;
width: 100%;
}
body{background: #333;}
#wrapper{
height: 100%;
width: 100%;
display: table;
}
.w1{
display: table-cell;
vertical-align: middle;
}
#row1{
height: 50px;
width: 600px;
background: #fff;
margin: 0 auto;
}
#row2{
height: 100px;
width: 800px;
background: #fff;
margin: 10px auto;
}
#row3{
height: 50px;
width: 500px;
background: #fff;
margin: 0 auto;
}
<div id="wrapper">
<div class="w1">
<div id="row1">Long Text</div>
<div id="row2">Long Text</div>
<div id="row3">Long Text</div>
</div>
</div>
It looks rubbish when I reduce width of browser and when I reduce the
height of the browser the divs overlap each other
Use percent units (or vw) instead of pixels.
I want the content to be placed in that 100% height of wrapper and
centered perfectly
Use flex on the container, with appropriate width and heights on the children.
Example Snippet:
html, body {
box-sizing: border-box;
margin: 0; padding: 0;
height: 100%; width: 100%;
}
#wrapper {
height: 100%; width: 100%;
display: flex; flex-direction: column;
align-items: center; text-align: center;
justify-content: space-around; /* to distribute space evenly around */
}
#wrapper > div { background-color: #ddd; }
#row1 { flex: 0 0 20%; width: 50%; } /* 0 0 means cannot grow cannot shrink */
#row2 { flex: 0 0 10%; width: 80%; }
#row3 { flex: 0 0 40%; width: 65%; }
<div id="wrapper">
<div id="row1">Long Text</div>
<div id="row2">Long Text</div>
<div id="row3">Long Text</div>
</div>
Sample Fiddle: http://jsfiddle.net/j3js87fc/1/
Update:
Alternatively, you could just use appropriate top/bottom margins on the row2 to have differing gaps between rows.
Example 2:
html, body {
box-sizing: border-box;
margin: 0; padding: 0;
height: 100%; width: 100%;
}
#wrapper { height: 100%; width: 100%; }
#wrapper > div { background-color: #ddd; }
#row1 { height: 20%; width: 50%; margin: auto; }
#row2 { height: 10%; width: 80%; margin: 3% auto 7% auto; }
#row3 { height: 40%; width: 65%; margin: auto; }
<div id="wrapper">
<div id="row1">Long Text</div>
<div id="row2">Long Text</div>
<div id="row3">Long Text</div>
</div>
Sample fiddle: http://jsfiddle.net/j3js87fc/4/
.
Here you go:
http://jsfiddle.net/oh36f1zb/4/
The left:50%; transform: translateX(-50%); does all the trick.

HTML - Footer not at the bottom

I want the footer be pushed down and appear as last element of the page. However as the content wrapper before has a height of 100%. The content's height exceeds the height of the browser height. In the end the footer appears after the browserheight and not after the content wrapper. How can I change it and still have a 100% height of the wrapper, that is needed for the background design.
codepen
HTML
<div class="content_wrap">
content wrap
<div class="item">content</div>
</div>
<footer>footer</footer>
CSS
body, html{
height: 100%;
}
.content_wrap{
height: 100%;
width: 100%;
border: 2px solid black;
}
.item{
height: 1300px;
width: 100%;
background: red;
}
footer{
height: 100px;
width: 100%;
background: yellow;
}
Give the body position property value of relative and position property value of absolute & bottom value of -(footer Height) for the footer
body {
height: 100%;
position: relative;
}
.content_wrap {
height: 100%;
width: 100%;
border: 2px solid black;
}
.item {
height: 1300px;
width: 100%;
background: red;
}
footer {
height: 100px;
width: 100%;
background: yellow;
position: absolute;
bottom:-100px; /* minus the height of the Footer and it wont overlap any other element */
}
<div class="content_wrap">
content wrap
<div class="item">content</div>
</div>
<footer>footer</footer>
footer{ position: fixed
bottom: 0px;
}
possible duplicate of: Bottom footer
If you use min-height: 100% instead of height: 100% on the content_wrap it will be at least 100% of the screen in height and it will grow if the content inside it is larger.
body, html{
height: 100%;
}
.content_wrap{
min-height: 100%;
width: 100%;
border: 2px solid black;
}
.item{
height: 1300px;
width: 100%;
background: red;
}
footer{
height: 100px;
width: 100%;
background: yellow;
}
<div class="content_wrap">
content wrap
<div class="item">content</div>
</div>
<footer>footer</footer>
body{
display:flex;
flex-flow:column;
height:100%;
}
header{
flex:0 0 75px;
}
.middle-container{
display:flex;
flex: 1 0 auto;
}
footer{
flex: 0 0 25px;
}
<header>Header</header>
<div class="middle-container">
content wrap
<div class="item">content</div>
</div>
<footer>footer</footer>