This question already has answers here:
Make a div fill the height of the remaining screen space
(41 answers)
Fill remaining vertical space with CSS using display:flex
(6 answers)
Closed 4 years ago.
I want to achieve the following behavior like in the image
So, I have a header with an arbitrary height and I want the container to fill the rest of the space. I have the following code:
<body>
<div class="header">
My header<br> Arbitrary height (ex: 123px)
</div>
<div class="container">
Container <br> Height = rest of the viewport
</div>
</body>
Note: I don't want to use .container{ height: calc(100% - 123px) } because the in the future 123px may change, so I don't want to modify in two places.
You can use flexbox for this:
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
display: flex;
flex-direction: column;
}
.header {
height: 123px; /* whatever height you want */
background:green;
}
.container {
flex-grow: 1;
background:beige;
}
<div class="header"></div>
<div class="container"></div>
See following example:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
html,
body {
height: 100%;
}
body {
min-height: 100%;
display: flex;
flex-direction: column;
padding:0;
margin:0;
}
.container {
flex: 1;
overflow:auto;
padding:10px;
}
.header {
background-color:green;
}
</style>
</head>
<body>
<div class="header">
<p>My header<br> Arbitrary height (ex: 123px)</p>
<p>My header<br> Arbitrary height (ex: 123px)</p>
</div>
<div class="container">
Container <br> Height = rest of the viewport
</div>
</body>
</html>
Related
This question already has answers here:
Prevent flex items from stretching
(2 answers)
Closed 3 years ago.
In the following image, the button is taking the height of the flexbox? Why? I want it to be a regular button bottom-aligned with the image on the left (the white square).
index.css
.grid-container{
display:grid;
grid-template-rows:[nav-row-start]auto [nav-row-end logo-nav-row-start] auto [logo-nav-row-end content-row-start] auto [content-row-end];
}
.nav-style{
height:5vh; /*make nav div take 5% of space of viewport*/
background-color:black;
}
.logo-nav-style{
height:20vh;/*make logo-nav div take 20% of space of viewport*/
background-color:gray;
}
.nav-flexbox-container{
display:flex;
flex-direction:row-reverse;
}
.logo-nav-flexbox-container{
display:flex;
}
.content-style{
height:75vh;/*make content div take 75% of space of viewport*/
background-color:white;
}
#nav{
grid-row:nav-row-start/nav-row-end;
margin:0px;
}
#logo-nav{
grid-row:logo-nav-row-start/logo-nav-row-end;
margin:0px;
}
#content{
grid-row:body-row-start/body-row-end;
margin:0px;
}
#profile-pic {
margin:5px;
}
#mail-icon-pic{
margin:5px;
}
#stats-icon-pic{
margin:5px;
}
#logo-image{
/*the max width and max height rule will make the image fit inside the div. If the image is bigger than div, the image will
contract, if the image is smaller than the div, the image will expand*/
max-width:100%;
max-height:100%;
}
body{
margin:0px;
}
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="index.css">
<title>Something</title>
</head>
<body>
<div class="grid-container">
<div id="nav" class="nav-style nav-flexbox-container">
<img id="stats-icon-pic" src="stats_icon.png">
<img id="mail-icon-pic" src="mail_icon.png">
</div>
<div id="logo-nav" class="logo-nav-style logo-nav-flexbox-container">
<img id="logo-image" src="example_logo.png">
<button type="button">Questions</button>
</div>
<div id="content" class="content-style">body</div>
</div>
</body>
</html>
The align-items flexbox property is set to stretch. See CSS tricks on flexbox.
Use this:
.logo-nav-flexbox-container{
display:flex;
align-items: flex-start;
}
I had to add align-items: flex-end rule
.logo-nav-flexbox-container{
display:flex;
align-items: flex-end;
}
I have a similar case in my project:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.wrapper {
display: flex;
width: 600px;
height: 300px;
}
.container {
display: flex;
width: 100%;
}
img {
height: 100%;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="image-wrapper">
<img src="https://placehold.co/200x600">
</div>
<h2>text</h2>
</div>
<div>
test
</div>
</div>
</body>
</html>
I have fixed width container (.container) that sets the height of its children to match its own height (due to align-items: stretch; by default). In one of those containers, I have an image (<img>) that I want to be the same height as its parent (.image-wrapper) while maintaining proportions. In the demo, that happens, but the .image-wrapper width is not updated. At least not always...
Sometimes, the image appears like this (incorrect):
...and sometimes, it appears like this (correct):
I think it has to do with the browser not updating the width of .image-wrapper. In the incorrect scenario, it has a width of 200 (the placeholder image's original size), but after the image is resized down to 100x300 (due to its height: 100% and its parent being 300px while having a natural size of 200x600) the parent's width is not updated to reflect that. It should change from 200 to 100, the image's now resized value.
One weird thing is that if the size is incorrect and you add width: 100% to .image-wrapper in the inspector and then remove it, its width is refreshed and is now displayed correctly.
If you download the snippet and open it in your browser, you should see that the image is displayed incorrectly until you open DevTools and disable cache. After that (because the image takes some time to load I guess), the width is set correctly upon refreshing.
This happens on latest Chrome, Firefox and IE11 on Windows 10. Here's a fiddle too.
Why does that happen? How to fix it?
As is, apparently this is a known bug in Chrome, but to my confusion I am also experiencing this in Firefox...
There is 2 solutions to this:
1)
img{
height: 100%;
width: 100px; /* Set a specific width to your image */
}
2) Apparently removing the image-wrapper div also solves this problem immediately.
.wrapper {
display: flex;
flex-flow: row nowrap;
flex-basis: 600px;
height: 600px;
}
.container {
display: flex;
height: 300px;
}
img {
height: 100%;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="wrapper">
<div class="container">
<img src="https://placehold.co/200x600">
<h2>text</h2>
</div>
<div>
test
</div>
</div>
</body>
</html>
This might happen when you don't specify explicitly the size of the image; notably, this is a known bug in Chrome.
You can either:
Specify that in either the HTML width attribute, or the CSS width property:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.wrapper {
display: flex;
width: 600px;
height: 300px;
}
.container {
display: flex;
width: 100%;
}
img {
height: 100%;
width: 100px; /* 1st solution: you should use fixed width when using CSS */
}
</style>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="image-wrapper">
<img src="https://placehold.co/200x600" width="100"> <!-- 2nd solution -->
</div>
<h2>text</h2>
</div>
<div>
test
</div>
</div>
</body>
</html>
Use JavaScript to set the HTML width attribute to the actual image size at runtime:
// Give your image a proper ID
window.addEventListener('load', function () {
var img = document.getElementById('img');
// This sets the image's HTML width element
// Notice the self-assignment
img.width = img.width;
})
.wrapper {
display: flex;
width: 600px;
height: 300px;
}
.container {
display: flex;
width: 100%;
}
img {
height: 100%;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="image-wrapper">
<img src="https://placehold.co/200x600" id='img' />
</div>
<h2>text</h2>
</div>
<div>
test
</div>
</div>
</body>
</html>
I've read quite a few similar questions to mine but none is quite the same or has an answer which works for me.
I'm using Twitter Bootstrap 3. I have two rows, and each row contains a col-sm-12 div, so they're the same width. The content in the first row is wider than its container but I have overflow:auto set on the element containing the two rows so a horizontal scrollbar is displayed and the content can be seen using that, so that's fine.
In the second row I have a div to which I'm applying a jQuery plugin (jqxGrid, for what it's worth). I've set the width option of the plugin to be "100%". The resultant grid's content is also too wide for its container but because of the way the jQuery plugin creates the grid it constricts the grid's width to 100% of its parent's width rather than overflowing.
So what I really need is for the .row elements to all be as wide as the widest overflowing content so that when the jQuery plugin evaluates the width of its parent so as to set its own width, the resultant grid ends up being as wide as the overflowing content in the first row.
I've made a fiddle which I hope will illustrate the problem. I feel that at its heart this is a CSS problem so a pure CSS solution would be excellent, but I doubt that that's possible.
.wrapper {
color: #fff;
padding: 10px;
}
.container-fluid {
background-color: #333;
overflow: auto;
}
.row1 {
background-color: yellow;
}
.row2 {
background-color: orange;
}
.short-content {
background-color: red;
width: 100%;
}
.long-content {
width: 2000px;
background-color: blue;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div class="wrapper">
<div class="container-fluid">
<div class="row row1">
<div class="col-sm-12">
<div class="long-content">
Long content
</div>
</div>
</div>
<div class="row row2">
<div class="col-sm-12">
<div class="short-content">
THe jQuery plugin here is too wide to fit but won't overflow because its width is set to match its parent.
</div>
</div>
</div>
</div>
</div>
To my understanding, wrapping each .col-sm-12 into their own parent .row is a verbose way of having all .col-sm-12 in a single .row container, as .col-sm-12s are always wrapping into a new line.
So, in case your setup allows for removing the intermediate .row tags, the only additional line of css you have to write is float: left; on .row. (In the example below I used the id #custom on .container-fluid to isolate this modification from the rest of your page).
body {
color: #fff;
padding: 10px;
}
.container-fluid {
background-color: #333;
overflow: auto;
}
.row1 {
background-color: yellow;
}
/*.row2 {
background-color: orange;
}*/
.short-content {
background-color: red;
width: 100%;
}
.long-content {
width:2000px;
background-color: blue;
}
#custom .row {
float: left;
}
<div id="custom" class="container-fluid">
<div class="row row1">
<div class="col-sm-12">
<div class="long-content">
Long content
</div>
</div>
<!-- </div> -->
<!-- <div class="row row2"> -->
<div class="col-sm-12">
<div class="short-content">
THe jQuery plugin here is too wide to fit but won't overflow because its width is set to match its parent.
</div>
</div>
</div>
</div>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
I'm trying to align the layout so the images align in a row.
Here's a image of what it is currently doing
HTML
<div class="p-alignleft"></div>
<div class="p-alignright"></div>
CSS
.p-alignleft {
float: left;
margin-right:40px;
width:450px;
font-size: 1.2em;
line-height: 1.4em;
}
.p-alignright {
float: right;
width:450px;
font-size: 1.2em;
line-height: 1.4em;
}
By looking at the captured screen, I think you should enclose each person's part inside a div, and give them classes .p-alignleft or .p-alignright. After every two of them, make an empty <div class="clear"></div> with style .clear {clear:both}, so the next two persons will align at the same vertical level
HTML:
<div class="p-alignleft">Person A</div>
<div class="p-alignright">Person B</div>
<div class="clear"></div>
<div class="p-alignleft">Person C</div>
<div class="p-alignright">Person D</div>
CSS:
.p-alignleft {float:left}
.p-alignright {float:right}
.clear {clear:both}
If I understand rightly, you have a couple of options here. Instead of floating, my preference is to set each div to display: inline-block; That will make the divs line up next to each other, even if one is taller than the other:
div {
display: inline-block;
vertical-align: top;
}
A working example: http://cdpn.io/ojDEl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
.wrap {width: 800px;}
.wrap div {width: 48%; display: inline-block; vertical-align: top; background: #e7e7e7; margin-bottom: 20px;}
/* temp demo styles */
.wrap div {height: 200px;}
.wrap div.test {height: 300px;}
</style>
</head>
<body>
<div class="wrap">
<div>Person A</div>
<div class="test">Person B</div>
<div>Person C</div>
<div>Person D</div>
</div>
</body>
</html>
Use a container div as a row element <div class="row clearfix"><div class="media">...</div></div>
Float both elements to the left, and set clear: left on the odd ones.
Use a javascript solution to set the height to be the same. then you can leave the clear left, right, or clear all to one side.
something like this, you probably need to tweak it, it's more like pseudo code.:
var maxHeight = 0;
var items = $('.media');
// get the max height of the items
items.each(function() {
var height = parseInt($(this).outerHeight().replace('px', ''), 10);
if (maxHeight < height) {
height = maxHeight;
}
});
// assign the height to all the items
items.height(height + 'px');
I have a simple HTML page with 3 "columns" (300px x 100%) that all have a vertical scrollbar. This works fine when having a window of at least 900 pixels in width. However, when I resize the window to be smaller than the columns take, one (or more) of the columns jump down to fit the window vertically. This is not what I want, because it would require the user to scroll all the way down before being able to see the other column.
What I want is pretty simple: a way to force the browser to fit the columns horizontally, even if it doesn't fit. width: 900px; on the body isn't a solution I want to use because the number of columns (and their width) is variable.
In other words: how do I force a browser to put my elements horizontally on a page and stop moving elements?
[edit]
My current code (well, it's not the actual code, but it does show what the problem is):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
* {
margin: 0;
padding: 0;
}
body, html {
height: 100%;
}
body {
overflow-x: scroll;
}
.column {
width: 300px;
height: 100%;
float: left;
overflow-x: hidden;
overflow-y: scroll;
}
</style>
</head>
<body>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</body>
</html>
The three "columns" need to be in a single container with the container's CSS set to 'nowrap'
<div style='white-space: nowrap;'>
<div id='col1'></div>
<div id='col2'></div>
<div id='col3'></div>
</div>
<!DOCTYPE html>
<html>
<head>
<style>
* { margin: 0px; padding: 0px; }
body, html { height: 100%; }
body {
overflow-x: scroll;
white-space: nowrap; // prevent 'text' from wrapping
}
.column {
display:inline-block; // make them behave like 'text'
width: 300px; height: 100%;
overflow-x: hidden; overflow-y: scroll;
}
</style>
</head>
<body>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</body>
</html>
AFAIK there's no cross browser way to force semantic columns (without JavaScript).
here is the answer I gave to a similar question.
HTML:
<div class="parent">
<div class="child">...</div>
<div class="child">...</div>
<div class="child">...</div>
</div>
CSS
.parent
{
display: table-row;
}
.child
{
display: table-cell;
width: 300px;
}
I believe IE < 9 has issues with this, so you'll need to set the sizing and positioning manually with JS for IE.