I am having some problems with the last child / the last child's margin being hidden outside the page/it's parent while the parent has max-height: -webkit-fill-available; height: auto; display:inline-block; and overflow: auto, as seen at https://jsfiddle.net/andreasjj/ok9hqgxv/2/
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
body, html {
font-size: 16px;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
height: 100vh;
display: flex;
flex-direction: column;
}
#root {
height: inherit;
min-height: inherit;
overflow: hidden;
}
#wrapper {
display: flex;
flex-direction: column;
height: inherit;
min-height: inherit;
width: inherit;
}
#header {
display: flex;
flex-direction: row;
align-items: center;
min-height: 50px;
width: inherit;
background-color: #f8f8f8;
}
#container {
display: flex;
flex-direction: row;
width: inherit;
height: inherit;
}
#content {
height: inherit;
width: 100%;
overflow: hidden;
}
#box {
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
height: inherit;
width: inherit;
}
#box-content {
max-height: -webkit-fill-available;
height: auto;
overflow: auto;
display: inline-block;
padding: 0.75rem;
width: calc(100vw - 1.0rem);
max-width: 900px;
}
.module {
background-color: black;
border: 1px solid #e9e9e9;
padding: 1.0rem;
margin-bottom: 3rem;
width: 541px;
height: 461px;
}
.module:first-child {
margin-top: 3rem;
}
</style>
</head>
<body>
<div id="root">
<div id="wrapper">
<div id="header"></div>
<div id="container">
<section id="content">
<div id="box">
<div id="box-content">
<div class="module"></div>
<div class="module"></div>
</div>
</div>
</section>
</div>
</div>
</div>
</body>
</html>
The last black box is missing most of its margin which is hidden (and if you remove the margin, part of the box itself will be hidden).
I have tried to change the height, max-height of different ancestors, in addition to different display values. But nothing seem to work. Any ideas?
The structure of the html might seem a bit weird, but this is html and css extracted from a react app, so I'd like to keep the structure somewhat similar to not break the whole thing.
I'm not sure I fully understand your problem, but what I always start my CSS scripts with, is the following piece of code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
The * means 'select everything' and the box-sizing makes sure that all the extra's like margins and borders are included in the size of an object.
https://www.w3schools.com/css/css3_box-sizing.asp
Hope it works for you!
Related
I am creating a div which is centered to the window. It's content can grow, and if it grows passed the size of the window, the content div should have it's scrollbar account for the overflow. But instead, the div just grows off the screen and gets clipped. If I set an explicit height on the content, everything works, but since I don't know the explicit height of the environment I cannot do that. What is the correct way to do this?
JSFiddle: https://jsfiddle.net/CodeVirtue/cjhz31xq
Here is the template:
<div class="fullscreen-overlay">
<div class="fullscreen-container">
<div class="window-with-titlebar">
<div class="titlebar">
<div class="titlebar-left">
Left
</div>
<div class="titlebar-right">
Right
</div>
</div>
<div class="content">
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40
</div>
</div>
</div>
</div>
And all the CSS:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.fullscreen-overlay {
background-color: red;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
padding: 12px 12px;
}
.fullscreen-container {
background-color: orange;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.window-with-titlebar {
background-color: yellow;
max-width: 100%;
max-height: 100%;
}
.titlebar {
background-color: green;
display: flex;
align-items: center;
justify-content: space-between;
height: 30px;
}
.titlebar-left {
background-color: darkgreen;
}
.titlebar-right {
background-color: lightgreen;
}
.content {
background-color: blue;
overflow-y: scroll;
max-width: 100%;
max-height: 100%;
}
I believe I was able to achieve what you are looking for by making the parent container use flexbox:
.window-with-titlebar {
background-color: yellow;
max-width: 100%;
max-height: 100%;
display: flex;
flex-direction: column;
}
I am trying to make a navbar using flexbox. In my code I have the actual navbar wrapped with flex- direction:"row" to align the logo and the button.
Now I want to have the nav-inner (the beige div) under the navbar (that should be 100vw wide), but actually it sits next to the navbar.
I have tried to change the flex-direction to "column" inside my nav-menu div, but the Hamburger button goes out of the screen. Am I doing something wrong?
body {
margin: 0;
overflow: hidden;
}
/* defaults */
.safe-view {
display: flex;
height: 100vh;
}
.hamburger {
height: 30px;
width: 30px;
}
/**/
/* navbar */
.navbar {
position: sticky;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30px;
width: 100vw;
font-size: 1.2em;
height: 100px;
}
.nav-menu {
width: 100%;
display: flex;
flex-direction:row;
/*flex-direction:column;*/
position: absolute;
height: 100%;
overflow: hidden;
background-color: white;
}
.nav-inner {
height: 100%;
width: 100%;
background-color: blanchedalmond;
}
/**/
<div class="safe-view">
<div class="nav-menu">
<div class="navbar">
<h1>logo</h1>
<button class="hamburger"></button>
</div>
<div class="nav-inner"></div>
</div>
</div>
This is a CSS box-model issue. You need to add box-sizing: border-box. This will ensure that padding is included in calculation of the width.
*{
box-sizing: border-box;
}
By default box-sizing is set to content-box. This will only care about the element content and shift padding and border outside of the element. That is why you saw the button push out to the right! This can also help you to understand further.
Also, flex-direction for .nav-menu needs to be set to column in order to position .nav-inner below.
Heres an alternative. I removed padding and just used calc() function to create padding. But always include box-sizing:border-box in your CSS :)
*{
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.safe-view {
display: flex;
height: 100vh;
}
.navbar {
position: sticky;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
width: calc(100vw - 60px);
margin: 0 auto;
font-size: 1.2em;
height: 100px;
}
.nav-menu {
width: 100%;
display: flex;
flex-direction:column;
position: absolute;
height: 100%;
overflow: hidden;
background-color: white;
}
.nav-inner {
height: 50px;
width: 100%;
background-color: blanchedalmond;
}
<div class="safe-view">
<div class="nav-menu">
<div class="navbar">
<h1 class="logo">logo</h1>
<button class="hamburger">button</button>
</div>
<div class="nav-inner"></div>
</div>
</div>
I am trying to fit 4 divs within the view bounds of a non-scrolling column flexbox but I can't seem to get it working.
What I want:
What I experience:
I have no idea what I am doing and just randomly permutating flex-related CSS fields to try and fix it haha. If someone could point out what is wrong I would love you forever.
Here is the gist of my code:
body {
overflow: hidden;
margin: 0;
width: 100%;
height: 100%;
}
#flexcontent {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
#header #firstContent #secondContent {
flex: 1 1 auto;
}
#header {
background-color: green;
font-weight: 700;
align-content: center;
font-size: 7rem;
}
#firstContent {
background-color: red;
}
#secondContent {
background-color: yellow;
}
#picture {
background-color: blue;
flex: 0 1 auto;
}
<body>
<div id="flexcontainer">
<div id="header">Title</div>
<div id="picture"><img src="https://s3-us-west-2.amazonaws.com/uw-s3-cdn/wp-content/uploads/sites/6/2017/11/04133712/waterfall-1140x760.jpg"/></div>
<div id="firstContent">first</div>
<div id="secondContent">second</div>
</div>
</body>
Try this below. And use object-fit if image doesn't expand or shrink as expected or aspect ratio changes.
#flexcontainer {
display: flex;
flex-direction: column;
height: 100vh;
}
#picture {
flex: 1;
min-height: 0;
}
body {
margin: 0;
}
img {
object-fit: contain;
height: 100%;
width: auto;
}
<div id="flexcontainer">
<div id="header">Title</div>
<div id="picture"><img src="https://s3-us-west-2.amazonaws.com/uw-s3-cdn/wp-content/uploads/sites/6/2017/11/04133712/waterfall-1140x760.jpg" /></div>
<div id="firstContent">first</div>
<div id="secondContent">second</div>
</div>
Please check your container div id
<div id="flexcontainer">
change
#flexcontent {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
to
#flexcontainer {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
try object-fit for img
img {
object-fit: contain;
height: 100%;
}
there is a few thing to fix in your CSS, typo and value used
html, /* to inherit height */
body {
margin: 0;
width: 100%;
height: 100%;
}
#flexcontainer {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
min-height: 0; /* force size calculation*/
}
#header,/* you meant each one of them */
#firstContent,
#secondContent {
flex: 1;
margin: 2px 5vw;/* for demo */
}
#header {
background-color: green;
font-weight: 700;
/* align-content: center; or did you forget display:flex here */
font-size: calc(1rem + 2vw);
}
#firstContent {
background-color: red;
}
#secondContent {
background-color: yellow;
}
#picture {
display: flex;
min-height: 0; /* force size calculation*/
}
img {
max-height: 90%;/* whatever */
margin: auto;/* or align-content + justify-content : center on flex parent*/
}
<div id="flexcontainer">
<div id="header">Title</div>
<div id="picture"><img src="https://s3-us-west-2.amazonaws.com/uw-s3-cdn/wp-content/uploads/sites/6/2017/11/04133712/waterfall-1140x760.jpg" /></div>
<div id="firstContent">first</div>
<div id="secondContent">second</div>
</div>
Allow the item holding the image to shrink below its content size.
Define the parameters of the image.
(Tested in Chrome, Firefox and Edge.)
#flexcontainer {
display: flex;
flex-direction: column;
height: 100vh;
}
#picture {
min-height: 0;
background-color: blue;
}
#picture>img {
width: 100%;
max-height: 100%;
object-fit: contain;
}
#header {
background-color: green;
font-weight: 700;
font-size: 7rem;
}
#firstContent {
background-color: red;
}
#secondContent {
background-color: yellow;
}
body {
margin: 0;
}
<div id="flexcontainer">
<div id="header">Title</div>
<div id="picture"><img src="https://s3-us-west-2.amazonaws.com/uw-s3-cdn/wp-content/uploads/sites/6/2017/11/04133712/waterfall-1140x760.jpg" /></div>
<div id="firstContent">first</div>
<div id="secondContent">second</div>
</div>
jsFiddle demo
I've tidied up your html a little and simplified the CSS. You want to take the overflow: hidden off of the body tag, and give each of your elements a class instead of an id. Finally, simplify the image section by making the image tag itself a flexbox item:
html,
body {
height: 100%
}
body {
/*overflow: hidden;*/
margin: 0;
}
.flexContainer {
display: flex;
flex-direction: column;
height: 100%;
}
.flexContainer__header,
.flexContainer__firstContent,
.flexContainer__secondContent {
flex: 1 1 auto;
}
.flexContainer__header {
background-color: green;
font-weight: 700;
align-content: center;
font-size: 7rem;
}
.flexContainer__firstContent {
background-color: red;
}
.flexContainer__secondContent {
background-color: yellow;
}
.flexContainer__picture {
display: block;
width: 100%;
}
<div class="flexContainer">
<div class="flexContainer__header">Title</div>
<img class="flexContainer__picture" src="https://s3-us-west-2.amazonaws.com/uw-s3-cdn/wp-content/uploads/sites/6/2017/11/04133712/waterfall-1140x760.jpg" />
<div class="flexContainer__firstContent">first</div>
<div class="flexContainer__secondContent">second</div>
</div>
First of all, the first snippet below is the problem I'm trying to fix.
Note that this was working perfectly fine IF display: flex; is applied to body.
However, I do not want to apply style to body which will break Google Web Cache layout.
* More explanation after the first snippet
* { box-sizing: border-box; }
body { margin: 0; }
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
background-color: #ccc;
}
.navigation {
background-color: #f00;
width: 100%;
height: 3rem;
}
.footer {
background-color: #0f0;
width: 100%;
text-align: center;
line-height: 2rem;
}
.content {
background-color: #ff0;
flex: 1;
margin: 0.6rem 0 1.2rem;
}
.container {
background-color: #f0f;
margin: 0 auto;
max-width: 120rem;
width: 100%;
padding: 0 2rem;
}
.centered {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
.long-content {
background-color: #fff;
}
<main class="wrapper">
<nav class="navigation">.navigation</nav>
<div class="content">
<section class="container centered">
<div class="long-content">.long-content</div>
</section>
</div>
<footer class="footer">.footer</footer>
</main>
So, removing display: flex; raised this issue:
section within .content does not have the height spanning across .content
Trying to fix it with position: relative on .content and position: absolute on .centered fixed the height issue but raised:
Width of .centered does not span across .content which can be easily fixed with left:0;right:0;
Height does not flow with content in section (I'm out of idea here)
Was it wrong to use position: relative and position: absolute to patch the original issue?
If so, what is the more suitable solution?
* { box-sizing: border-box; }
body { margin: 0; }
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
background-color: #ccc;
}
.navigation {
background-color: #f00;
width: 100%;
height: 3rem;
}
.footer {
background-color: #0f0;
width: 100%;
text-align: center;
line-height: 2rem;
}
.content {
background-color: #ff0;
flex: 1;
margin: 0.6rem 0 1.2rem;
position: relative;
}
.container {
background-color: #f0f;
margin: 0 auto;
max-width: 120rem;
width: 100%;
padding: 0 2rem;
}
.centered {
display: flex;
position: absolute;
height: 100%;
left: 0;
right: 0;
align-items: center;
justify-content: center;
}
.long-content {
background-color: #fff;
height: 1000px;
}
<main class="wrapper">
<nav class="navigation">.navigation</nav>
<div class="content">
<section class="container centered">
<div class="long-content">.long-content</div>
</section>
</div>
<footer class="footer">.footer</footer>
</main>
I continued looking for solution and quickly noticed that I have shallow knowledge about flexbox itself so I went ahead and played with Flexbox Froggy.
After completing all the levels, I noticed that I can align everything without position: absolute by just using justify-content on .wrapper.
Below is my solution for my silly issue.
If you remove height of .long-content, .centered will continue to get aligned vertically.
Thank you froggies and shout out to Codepip!
* { box-sizing: border-box; }
body { margin: 0; }
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
background-color: #ccc;
justify-content: space-between;
}
.navigation {
background-color: #f00;
width: 100%;
height: 3rem;
}
.footer {
background-color: #0f0;
width: 100%;
text-align: center;
line-height: 2rem;
}
.content {
background-color: #ff0;
margin: 0.6rem 0 1.2rem;
}
.container {
background-color: #f0f;
margin: 0 auto;
max-width: 120rem;
width: 100%;
padding: 0 2rem;
}
.centered {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
.long-content {
background-color: #fff;
height: 1000px;
}
<main class="wrapper">
<nav class="navigation">.navigation</nav>
<div class="content">
<section class="container centered">
<div class="long-content">.long-content</div>
</section>
</div>
<footer class="footer">.footer</footer>
</main>
This question already has answers here:
How can I vertically center a div element for all browsers using CSS?
(48 answers)
Closed 5 years ago.
I've been learning CSS and am now practicing by trying to replicate basic websites, but I've stumbled across a problem!
I'm trying to vertically align a box so that it is always in the middle, and will automatically scale if I make the browser vertically smaller. So far I've tried to replicate what I've done horizontally (normally margin: 0 auto;) but it isn't working.
My relevant HTML and CSS so far look like this:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
I'm showing the borders so I can see what's going on, and am sure that (like horizontal centering) my margins need to be automatic. When I've done this horizontally, it's worked fine...
Does anyone have a recommendation on what to do??
Thanks in advance!
Flexbox is your friend! You need to add the following to your container styles
display: flex;
align-items: center;
justify-content: center;
We're setting the display to flex/flexbox with display: flex; and aligning everything to the center with align-items: center; and justify-content: center;
With all the vendor-prefixes it looks like:
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
Check this: https://codepen.io/danieldd/pen/pdooVN
<div class="container">
<div class="item-centered"></div>
</div>
.container {
height: 400px;
width: 100%;
background-color: cyan;
display: flex; /*this is needed for centering*/
align-items: center; /*this center vertically childred elements*/
justify-content: center; /*this center horizontally childred elements*/
}
.item-centered {
height: 200px;
width: 200px;
background-color: red;
}
Sadly the auto margins trick only works horizontally. In CSS3, you can use another trick. You start with top: 50%; and then subtract half the height of your container using transform: translateY(-50%);. The perspective(1px) is just to correct the calculation to a whole pixel and prevent issues in some browsers. See the three lines I've added to your CSS:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html {
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body {
background-color: #f9f9f9;
height: 100%;
}
.container {
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header {
border: solid;
min-height: 100px;
margin: auto 5%;
position: relative;
top: 50%;
transform: perspective(1px) translateY(-50%);
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<a href="mailto:jon#jonphillips.ca" target="_blank">
<p>Contact</p>
</a>
</nav>
</header>
</div>
</body>
On the parent of the item that you're trying to center, you can just use display: flex; and the child should center inside (with the rest of the styles that you already have set up).
This could also be achieved using absolute positioning, though it would be a few more lines:
.parent {
position: relative;
}
.child {
/* Vertically center - will still need left / right & width adjustment otherwise */
position: absolute;
top: 50%;
transform: translateY(-50%);
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
display: flex;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
width: 100%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
There are different approuces to solve this problem, the easyest and with a good compatibility is the use of the "table-cell display", so in your case adding this to your CSS:
.container {
display:table-cell;
height:100%;
vertical-align:middle
}
The point is that a correct implementation of a table-cell should consider the parent element as a table, your parent element is the body itself, so do change your CSS into:
body{
background-color: #f9f9f9;
height: 100%;
width:100%;
display:table
}
http://jsfiddle.net/9tghnydg/
On a second though the height propriety on the .container is not strictly necessary, acting it as the unique cell of the body table:
.container {
display:table-cell;
vertical-align:middle
}
http://jsfiddle.net/9tghnydg/1/