I need to do this :
div container 800x600 px
div header 800x150 px
div under header 800x50 px
div menu 200x350 px
div content 600x350 px
div footer 800x50 px
I need to put all this 5 divs inside 1 div, each div must have different colors.
By default, block-level elements expand to 100% of the width of the containing element and their height is determined by their contents. So most of the work here is done for you already by default.
You can set a width for the containing element and heights for the inner element. That gets you almost all of the way there. You just need to make the menu and content sit side by side. You can do this with CSS grid, flexbox, display: table, or floats.
Also, <div> elements are the wrong choice here. HTML includes a lot of different element types, such as <header>, <footer>, <nav>, and <main> that you should consider using.
All you need to do is just assign height to each element and width as per your need, rest give display:flex; flex-wrap: wrap to its parent, and it will handle everything
* {margin: 0; padding:0; box-sizing: border-box;}
.wrapper {max-width: 800px; width: 100%; margin: 0 auto;display: flex;flex-wrap: wrap;}
header {
height: 150px;
background-color: #FF009C;
width: 100%;
}
.yellow50 {
height: 50px;
background-color: #D8FF00;
width: 100%;
}
.blue350, .orange350 {height: 350px; width: 50%;}
.blue350 {
background-color: #03907A;
}
.orange350 {
background-color: #FF7E00;
}
footer {
height: 50px;
background-color: #0B561B;
width: 100%;
}
<section class="wrapper">
<header></header>
<div class="yellow50"></div>
<div class="blue350"></div>
<div class="orange350"></div>
<footer>
</section>
CSS grid layout is one option here:
<!DOCTYPE html>
<html>
<head>
<title>SO 61631033: how-to-put-3-divs-inside-1-div</title>
<style type="text/css">
#container {
display: grid;
grid-template-areas:
"h h"
"sh sh"
"m c"
"f f";
grid-template-rows: 150px 50px 350px 50px;
grid-template-columns: 200px 600px;
width: 800px;
height: 600px;
}
#content {
background-color: darkgreen;
grid-area: c;
}
#footer {
background-color: orange;
grid-area: f;
}
#header {
background-color: pink;
grid-area: h;
}
#menu {
background-color: green;
grid-area: m;
}
#subheader {
background-color: yellow;
grid-area: sh;
}
</style>
</head>
<body>
<div id="container">
<div id="header"></div>
<div id="subheader"></div>
<div id="footer"></div>
<div id="menu"></div>
<div id="content"></div>
</div>
</body>
</html>
Develop this design by starting with a rectangular tesselation of the screen estate. Each rectangle represents a container element in html. Superimpose a grid with all tile borders on grid lines. The grid does not need to be equi-spaced in any dimension. This grid is the base for the grid-template-areas CSS property that mirrors the tesselation in an obvious way.
There are a host of additional options how to specify a grid layout, especially tuned to more regular tilings. MDN has their own section on layouting with this methodology.
If support of different devices and responsive design is of primary concern, flex layout will suit the task better.
Related
In my site I have the following structure:
Header
Content
Footer
And I want to make the Header and the Footer size based on their content (not a fixed size). And the Content to fill the remaining space.
I saw many questions and answers like: Make a div fill the height of the remaining screen space
that solves similar cases but in my case, the Header and Footer sizes are unknown so I can't use the calc() function, and the Header Has position:fixed which removes it from the layout calculations and makes the
flex solutions of various kinds wrong:
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row {
border: 1px dotted grey;
}
.box .row.header {
flex: 0 1 auto;
position: fixed;
/* The above is shorthand for:
flex-grow: 0,
flex-shrink: 1,
flex-basis: auto
*/
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
<!-- Source - https://stackoverflow.com/a/24979148-->
<div class="box">
<div class="row header">
<p><b>header</b>
<br />
<br />(sized to content)</p>
</div>
<div class="row content">
<p>
<b>content</b>
(fills remaining space)
</p>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
Or using this solution:
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.header{
position:fixed;
}
.content {
flex-grow: 1;
border: 1px dotted red;
}
<!-- Source - https://stackoverflow.com/a/28771764-->
<body>
<div class="header">header</div>
<div class="content"></div>
</body>
Is there any way to do make the Content height = 100% - FooterHeight - HeaderHeight
When the Footer and Header dimensions are unknown, and the Header has fixed position?
Since the header is fixed, I think you would need to know its height through JavaScript, and set the body's min-height as 100% of the viewport's height minus the header's height. After, you could simply use CSS Grid on body, to have the content take all the avaiblable height. Like so:
document.body.style.minHeight=`calc(100vh - ${document.querySelector("header").clientHeight}px)`;
document.body.style.paddingTop= document.querySelector("header").clientHeight + "px";
body{
margin:0;
display:grid;
grid-template-rows:1fr auto;
}
header{
background:lightblue;
position:fixed;
top:0;
left:0;
width:100%;
}
div{
background:lightgreen;
}
footer{
background:lightyellow;
}
<header>I'm the header</header>
<div>I'm the content</div>
<footer>I'm the footer</footer>
I can think of two solutions based on the rather general description of your problem:
A) Use JavaScript to do the calculations for you and apply the values to margins or positions, whichever works better in your case;
B) You could repeat the contents of the header (and footer, id that's out of the document flow also) in element(s) atop the content and make it transparent and non-inter-active (pointer-events: none) - dirty, but if JS is not an option and your header does not offer some other way to determine it's height through some 'css-magic' it might be the only solution.
Quite often I find, that there are better solutions when the problem is more specifically described, so if you can tell us what elements make it impossible to know the height of the header, there might be better solutions. Often when ratios as with images are in play, vh can come to the rescue - even though tha can be tricky too...
Finally I found a pure css solution.
since the Header is in the top , using position: sticky instead of fixed will have the same result but the layout will take it into account when calculating:
html,
body {
height: 100%;
margin:0;
}
body {
display: flex;
flex-direction: column;
}
.header{
position:sticky;
}
.content {
flex-grow: 1;
border: 1px dotted red;
}
<!-- Source - https://stackoverflow.com/a/28771764-->
<body>
<div class="header">header</div>
<div class="content"></div>
</body>
I'm trying to lay out a web page that has three reasons - left, top right and bottom right. The left and bottom right regions should have scrollbars in them, and the entire page should fill the screen. I'm using Bootstrap 4.
I can get the scrollbars working properly around the left region. The problem is with the right regions - the horizontal scrollbar appears on the bottom-right region, as it should, but the vertical scrollbar appears on the entire page. Note that the bottom-right also has a vertical scroll bar, but it's disabled.
#outer {
height: 100vh;
overflow: none;
}
#left-col {
height: 100vh;
overflow: scroll;
background-color: #ff85d4;
}
#left-large {
height: 5000px;
width: 5000px;
}
#right-col {
height: 100vh;
}
#right-top {
background-color: #abff64;
}
#right-bottom {
overflow: scroll;
background-color: #ccddff;
}
#right-bottom-inner {
width: 2000px;
height: 2000px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row" id="outer">
<div class="col-9" id="left-col">
<div id="left-large">
Large left
</div>
</div>
<div class="col-3" id="right-col">
<div id="right-top">
<p>
Top 1
</p>
<p>
Top 2
</p>
<p>
Top 3
</p>
</div>
<div id="right-bottom">
<div id="right-bottom-inner">
Right bottom inner
</div>
</div>
</div>
</div>
</div>
How can I make the bottom-right region have its own scrollbars?
Like I said in the comments this is another way to do this with CSS grid which seems like the perfect tool for something this ... "gridy" :)
I gave all the boxes plenty of space you can scroll... adjust at will.
Update: I made the right-top box max-content and grow for as long as the content is while giving the right-bottom box a min height of 20px.
body {
padding: 0;
margin: 0;
}
.wrapper {
display: grid;
grid-template-columns: 1.6fr 0.4fr;
grid-template-rows: max-content minmax(20px, 1fr);
gap: 1rem;
height: 100vh;
width: 100vw;
}
.wrapper-inner {
height: 2000px;
width: 2000px;
}
.left,
.right-top,
.right-bottom {
overflow: auto;
padding: 1rem;
}
.left {
grid-row-start: 1;
grid-row-end: 3;
background: hotpink;
}
.right-top {
background: lime;
}
.right-bottom {
background: skyblue;
}
<div class="wrapper">
<div class="left">
<div class="wrapper-inner">
Large left
</div>
</div>
<div class="right-top">
<p>
Top 1
</p>
<p>
Top 2
</p>
<p>
Top 3
</p>
</div>
<div class="right-bottom">
<div class="wrapper-inner">
Right bottom inner
</div>
</div>
</div>
If you want to force a scrollbar on any block element, you'll need to set a fixed height and include an overflow-x:scroll or overflow-y:scroll property depending on where you want the scrollbar to appear.
If you want a horizontal scrollbar, use overflow-x:scroll;, if you want a vertical scrollbar, use overflow-y:scroll;
flex is magic
CSS
/*Allow children to auto fixed height*/
#right-col {
display: flex;
flex-direction: column;
}
#right-top {
height: fit-content; /*Only use essential*/
}
#right-bottom {
overflow: scroll; /*See child content*/
height:100%; /*use all remain height*/
}
Seeing that the height needs to be explicit (either as percentage or a fixed number), I couldn't find a CSS-only solution.
Instead I used a ResizeObserver to track changes to the size of the right-col and right-top elements (in my actual problem, the right-top element changes in size), calculated the right-bottom element (right-col.height - right-top.height basically), and applied it as a dynamic style on the right-bottom element.
Not pretty but it's working.
I tried using a CSS grid, too (instead of bootstrap altogether), but without explicitly specifying the height of the right bottom element, the scrollbars misbehaved there, as well.
This question already has answers here:
Prevent content from expanding grid items
(3 answers)
Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
(1 answer)
Closed 2 years ago.
Edit: Let me clarify! I'm not asking about how to keep the content from flowing out by restricting the size of the container, what I'm looking for is how to properly adjust the size of the content based on the container and why a div with a background image set to cover works, while and img element does not.
I am trying to achieve a standard grid layout with a header, sidebar, content and footer, where the content element would have only a single image as a child, that should fill the entire remaining space. I thought that applying
img {
width: 100%;
height: 100%;
object-fit: cover;
}
would be enough to get the desired result, but it unexpectedly increased the height of the content element. What's even more absurd is that no matter how much I reduce the height of the image, as long as it is measured in percentages, the height of the container keeps depending on the width of the image. See the following pen (or look at the snippets below, but the issue is more apparent in the pen, since there the boxes are visible side-by-side) for example.
https://codepen.io/Isti115/pen/vYGRNpg
Try adjusting the .a img { widht: 100%; } and see how it affects the overall height.
.container {
display: inline-grid;
width: 400px;
height: 300px;
margin: 50px;
grid-template-rows: 75px 1fr 50px;
/* grid-template-rows: 75px minmax(0, 1fr) 50px; */
grid-template-columns: 100px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header {
grid-area: header;
background-color: red;
}
.sidebar {
grid-area: sidebar;
background-color: yellow;
}
.content {
grid-area: content;
background-color: green;
}
.footer {
grid-area: footer;
background-color: blue;
}
.a .content {
/* min-height: 0; */
}
.a img {
width: 100%;
height: 20%;
/* object-fit: cover; */
/* height: 100%; */
}
.b img {
width: 100%;
height: 50px;
/* object-fit: cover; */
}
.c .placeholder {
width: 100%;
height: 100%;
/* background-color: purple; */
background: url("http://lorempixel.com/200/150/cats");
background-size: cover;
}
<div class="container a">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container b">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container c">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<div class="placeholder"></div>
</div>
<div class="footer"></div>
</div>
I have since found a solution by either adding min-height: 0 or using minmax(0, 1fr), but I don't consider those ideal solutions, since I don't see why I couldn't simply take the remaining space that gets assigned to the content div element and place an image inside it that fills it completely without expanding the containers size. For example using a simple div instead of the image and giving it a background works perfectly as intended.
ps.: I know that this might sound similar to some other questions that got answered with max-height: 100%, but I think that there is a more complicated underlying issue that I would like to explore.
I need to display an image as large as possible in my layout. The image can be of any size and/or ratio, and it must work with landscape or portrait device orientation (responsive).
Actual CSS layout description
My layout is a simple CSS grid with:
a header on the top,
the main content where the image must fit (with a commands area on the bottom),
and a nav bar on the bottom.
The actual main area is a display:flex, in order to display some photo commands on the bottom, and the real img tag is wrapped into a div.photo-frame element, in order to display a large white border around the image.
Note: This border could have been rendered by a CSS border property on the image, but I would like to keep it as a <div>, in case if extra elements should be added into the white frame, below the image (e.g.: image caption, links...).
What I tried
I tried many things, but the div.photo-frame element causes problems because ~ it doesn't know the size of the image ~ (#forgivethenoob).
What I need
It would be really great if someone could adapt the one-file code I give just below to a working version.
I guess it is a trivial task for a CSS expert; sorry for duplicate.
Single file code (html+css)
Here is a full example (as minimal as possible, only the cat image is missing):
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title></title>
<style>
body, html {
width: 100%;
height: 100%;
margin: 0;
color: #aaa;
background-color: black;
}
.layout {
display: grid;
grid-template-rows:
4rem
auto
4rem;
grid-template-areas: "header" "main" "nav";
width: 100%;
height: 100%;
}
header {
grid-area: header;
background-color: #330;
}
main {
grid-area: main;
background-color: #033;
}
nav {
grid-area: nav;
background-color: #303;
}
#page-1 {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
#page-1 .photo-zone {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}
/* I prefer to use this class (.photo-frame) instead of a simple border property on the image,
* because some stuff might be added inside the white frame, below the image: */
#page-1 .photo-zone .photo-frame {
display: flex;
padding: 4px;
background-color: white;
border-radius: 0.2rem;
}
#page-1 .photo-commands {
background-color: rgba(255,255,255,0.1);
}
#cat {
width: 200px; /* This needs to be removed in order to answer the question */
}
</style>
</head>
<body>
<div class="layout">
<header>Header (fixed height)</header>
<main>
<div id="page-1">
<div class="photo-zone">
<div class="photo-frame">
<img id="cat" src="cat.jpg" />
</div>
</div>
<div class="photo-commands">
Photo commands
</div>
</div>
<div id="page-2" style="display:none"></div>
<div id="page-3" style="display:none"></div>
</main>
<nav>Nav bar (fixed height)</nav>
</div>
</body>
</html>
Here is a rendering of the above code (fixed size image: width=200px)
Here is what I would like in a landscape orientation
Here is what I would like in a portrait orientation
I am trying to take a nested div and make it scrollable but I am having some difficulty. The problem child is the div with the class named "items".
<body>
<div class="page-wrapper">
<div class="header">Header</div>
<div class="content-wrapper">
<div>I want the div below to scroll</div>
<div class="items">
<div>item</div>
...
</div>
</div>
</div>
</body>
body {
height: 100%;
min-height: 100vh;
overflow: hidden;
}
.page-wrapper {
display: grid;
grid-template-columns: 1fr;
justify-content: center;
height: 100%;
grid-template-rows: 50px 1fr;
}
.content-wrapper {
height: 100%;
}
.items {
overflow: scroll;
height: 100%;
width: 500px;
background-color: #fafafa;
}
.header {
background-color: orange;
}
Codepen Link:
https://codepen.io/allencoded/pen/abdmwmQ?editors=1100
I am not sure what is going on. I have set the overflow on items to be scroll, I figured that would do the trick but appears I am wrong. Is there a way to make the .items scroll like this? If not why?
reduce the height of the items class as 100% will display all contents.
If you set 100% at your height property from .items class, your <div> tag will expand until all nested items are shown. To enable your scroll , the height of the <div> with class .items must be lower to what it would have if your div expanded to accommodate all nested tags.
Try to set your height property lower than 100% or set in pixels (100px, for instance).