I have a simple grid with 2 rows: one serves as a header, the other one is a list of items. I want my grid to have a max height, and I want to be able to scroll my list of items.
Link to the codepen
<div class="grid">
<div class="two">
Two
</div>
<div class="three">
<div class="body">
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
</div>
</div>
</div>
.grid {
display: grid;
grid-template-rows: 50px min-content;
max-height: 300px;
background: blue;
overflow-y: hidden;
}
.two {
background: green;
}
.three {
background: #00000044;
max-height: 400px;
}
.body {
max-width: 400px;
background: orange;
margin: auto;
max-height: 100%;
overflow-y: scroll;
}
My .grid item has a max height, but still, if I had more items to my list, the whole grid expands. Is there a way to make sure my max height is taken into account ?
If you want to only scroll the list of items and keep the header in the same position you can use position: sticky, updated example:
.grid {
display: grid;
grid-template-rows: 50px min-content;
max-height: 300px;
background: blue;
overflow-y: auto;
}
.two {
background: green;
position: sticky;
top: 0;
}
.three {
background: #00000044;
}
.body {
max-width: 400px;
background: orange;
margin: auto;
max-height: 100%;
overflow-y: scroll;
}
<div class="grid">
<div class="two">
Two
</div>
<div class="three">
<div class="body">
<p>Section first</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section</p>
<p>Section last</p>
</div>
</div>
</div>
instead of overflow hidden use auto
code :
.grid {
display: grid;
grid-template-rows: 50px min-content;
max-height: 300px;
background: blue;
overflow-y: hidden;
}
.two {
background: green;
}
.three {
background: #00000044;
max-height: 400px;
}
.body {
max-width: 400px;
background: orange;
margin: auto;
max-height: 100%;
overflow-y: auto;
}
Is there some reason you can't set max-height to 300px on both .grid and .body ?
.body { max-height: 300px; }
Related
My question is similar to this one: I'm trying to contain an aspect-ratio element within its parent element. One difference though, this aspect-ratio element has siblings—a header and a footer—and all this nice family should be center-aligned and share a common width.
Images are worth a thousand words:
GIFs are worth a thousand images:
I'm close to that result, but I'm not quite there yet:
body {
height: 100%;
margin: 0;
}
html {
background-color: lightgrey;
height: 100%;
}
#footer,
#header {
background-color: blue;
height: 50px;
}
#paper {
aspect-ratio: 1;
background-color: red;
margin: auto;
max-height: 100%;
overflow: hidden;
width: 100%;
}
#wrapper {
align-content: center;
display: grid;
height: 100%;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
Any CSS wizard to help me out?
Not sure if you can get all the requirements but here is the best I could do (seems to work on chrome only)
body {
background-color: lightgrey;
margin: 0;
}
#footer,
#header {
background-color: blue;
height: 50px;
}
#paper {
aspect-ratio: 1;
background-color: red;
max-height: 100%;
max-width: 100vw;
}
#wrapper {
place-content: center;
display: grid;
height: 100vmin;
margin-block: max(0px,50vh - 50vmin);
grid-template-rows: auto minmax(0, 1fr) auto;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
If the 50px is known you can do like below:
body {
background-color: lightgrey;
margin: 0;
--h: 50px; /* the fixed height */
}
#footer,
#header {
background-color: blue;
height: var(--h);
}
#paper {
aspect-ratio: 1;
background-color: red;
width: min(100vw,100vh - 2*var(--h));
}
#wrapper {
place-content: center;
display: grid;
height: min(100vh, 100vw + 2*var(--h));
margin-block: max(0px, (100vh - 100vw - 2*var(--h))/2);
grid-template-rows: auto minmax(0, 1fr) auto;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
Try this solution, all the magic happens in grid-template-columns and grid-template-rows.
html {
background-color: lightgrey;
height: 100%;
}
body {
height: 100%;
margin: 0;
}
#wrapper {
--footer-header-height: 50px;
align-content: center;
display: grid;
height: 100vh;
grid-template-columns: 1fr minmax(auto, calc(100vh - var(--footer-header-height) * 2)) 1fr;
grid-template-rows: auto minmax(auto, 100vw) auto;
}
#footer,
#header {
grid-column: 2;
background-color: blue;
height: var(--footer-header-height);
}
#paper {
grid-column: 2;
aspect-ratio: 1 / 1;
background-color: red;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
Actually Container Queries enable us to solve this kind of problems elegantly.
Support for this feature is currently very bad (see here), but it's part of Interop 2022 so I guess it'll look different by the end of the year.
I post this as an answer as it might help someone in the future 👽👋
Note that you currently need to turn on a flag on Chrome to be able to test it.
body {
container-type: size;
height: 100%;
margin: 0;
}
html {
background-color: lightgrey;
height: 100%;
}
#footer,
#header {
background-color: blue;
}
#paper {
background-color: red;
}
#wrapper {
align-content: center;
display: grid;
grid-template-columns: min(100cqi, (100cqb - 100px));
grid-template-rows: 50px min(100cqb - 100px, 100cqi) 50px;
justify-content: center;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
Here's the same code but relying on viewport units (works in all browsers):
body {
height: 100%;
margin: 0;
}
html {
background-color: lightgrey;
height: 100%;
}
#footer,
#header {
background-color: blue;
}
#paper {
background-color: red;
}
#wrapper {
align-content: center;
display: grid;
grid-template-columns: min(100vw, (100vh - 100px));
grid-template-rows: 50px min(100vh - 100px, 100vw) 50px;
height: 100%;
justify-content: center;
}
<div id="wrapper">
<div id="header"></div>
<div id="paper"></div>
<div id="footer"></div>
</div>
So in resume, I have a #modal { max-height:90% } and I need to place a #footer element below and let the top remaing space to a scrollable div, but is not possible to have a scroll div without setting the height (or max-height, as far as I know).
The way I achieved this is calculating the height of the scrollable div, like so: https://codepen.io/murillotsoza/pen/xxpJPVJ (change the code view to the left/right side)
But I still think that there is a prettier solution without height calculations. Any tips?
#scroll {
max-height: calc(90vh - 18px - 50px);
overflow-y: auto;
overflow-x: hidden;
}
.item {
font-size: 18px; text-align: center;
line-height: 50px; width: 300px;
border-bottom: 1px solid #ccc;
}
#footer {
font-size: 18px; text-align: center;
line-height: 50px; width: 100%;
background-color: #333; color: white;
}
#title{
height: 18px;
background-color: black;
}
#content {
background-color: white;
}
#modal {
max-height: 90%;
overflow: hidden;
}
#background {
position: fixed;
top: 0; left: 0;
width: 100vw;
height: 100vh;
background-color: #eee;
display: flex;
justify-content: center;
align-items: center;
}
body { margin : 0; }
<div id='background'>
<div id="modal">
<div id="title"></div>
<div id="content">
<div id="scroll">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<div id="footer">FOOTER</div>
</div>
</div>
</div>
Here is a modern CSS grid solution:
You can change around your grid-template fraction units to give more room to your header, scroll area and footer respectively. Currently the 80% height is divided into 4, with 1fr given to your header, 2fr given to your scroll area, and 1fr given to your footer.
* {
box-sizing: border-box;
}
html,
body {
height: 100vh;
}
body {
display: grid;
place-content: center;
margin: 0;
background-color: #eee;
}
.modal {
display: grid;
grid-template: 1fr 2fr 1fr / auto;
width: 300px;
height: 80%;
overflow: hidden;
}
header {
background-color: black;
}
.scroll {
overflow-y: auto;
}
.item {
font-size: 1.1rem;
text-align: center;
line-height: 3rem;
border-bottom: 1px solid #ccc;
}
footer {
font-size: 1.1rem;
text-align: center;
background-color: #333;
color: white;
}
<article class="modal">
<header></header>
<div class="scroll">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<footer>FOOTER</footer>
</article>
Codepen: https://codepen.io/zachjensz/pen/MWrBVbv
In the snippet below you can see that the green .bottom stops at the width of the screen using a width of 100%. Can I force the width to match exactly the parent width? In this case 1000px.
The problem is that the red .top is a variable width so setting a fixed width for the green .bottom is not an option.
.parent {
width: 700px;
}
div.container {
overflow: auto;
background-color: yellow;
display: flex;
flex-direction: column;
height: 100px;
}
div.top {
background-color: red;
height: 40px;
width: 1000px;
}
div.bottom {
background-color: green;
height: 20px;
width: 100%;
}
<div class="parent">
<div class="container">
<div class="top"></div>
<div class="bottom"></div>
</div>
</div>
Use CSS grid instead of flexbox:
.parent {
width: 700px;
}
div.container {
overflow: auto;
background-color: yellow;
display: grid;
align-content: start; /* don't forget this */
height: 100px;
}
div.top {
background-color: red;
height: 40px;
width: 1000px;
}
div.bottom {
background-color: green;
height: 20px;
}
<div class="parent">
<div class="container">
<div class="top"></div>
<div class="bottom"></div>
</div>
</div>
I can't seem to have a horizontally-scrolling div inside a flex column.
Codepen
.container { display: flex; margin: 20px; height: 300px; border: 1px solid blue; }
.side-nav { flex-shrink: 0; width: 100px; min-height: 100%; background: grey; }
.main { padding: 20px; }
.scrollable { overflow-x: auto; max-width: 100%; }
.long-content { width: 2000px; height: 50px; background: red; }
<div class='container'>
<div class='side-nav'>
</div>
<div class='main'>
<h1>Test</h1>
<div class='scrollable'>
<div class='long-content'>
This is supposed to scroll horizontally unless your window is super wide
</div>
</div>
<p>Some paragraph below the scrollable box</p>
</div>
</div>
If I change the max-width of .scrollable to px it would work, but I need it to fill the column.
What am I missing?
In my opinion, this is a Module"bug" (Wierd).
Anyway, one very simple solution is to use flex-basis (Instead of width).
Step 1 for main add width: 0;
.container {
display: flex;
margin: 20px;
height: 300px;
border: 1px solid blue;
}
.side-nav { flex-shrink: 0; width: 100px; min-height: 100%; background: grey; }
.main {
padding: 20px;
border: 5px dashed orange;
/* "new code" */
width: 0px;
}
.scrollable { overflow-x: auto; max-width: 100%; }
.long-content { width: 2000px; height: 50px; background: red; }
<div class='container'>
<aside class='side-nav'>
Aside
</aside>
<main class='main'>
<h1>Test</h1>
<div class='scrollable'>
<div class='long-content'>
This is supposed to scroll horizontally unless your window is super wide
</div>
</div>
<p>Some paragraph below the scrollable box</p>
</main>
</div>
Step 2 - main add flex-basis: 100%;
.container {
display: flex;
margin: 20px;
height: 300px;
border: 1px solid blue;
}
.side-nav { flex-shrink: 0; width: 100px; min-height: 100%; background: grey; }
.main {
padding: 20px;
border: 5px dashed orange;
/* "new code" */
width: 0px;
flex-basis: 100%;
}
.scrollable { overflow-x: auto; max-width: 100%; }
.long-content { width: 2000px; height: 50px; background: red; }
<div class='container'>
<aside class='side-nav'>
Aside
</aside>
<main class='main'>
<h1>Test</h1>
<div class='scrollable'>
<div class='long-content'>
This is supposed to scroll horizontally unless your window is super wide
</div>
</div>
<p>Some paragraph below the scrollable box</p>
</main>
</div>
One more option is to use width: 0; & flex-grow:1
.container {
display: flex;
margin: 20px;
height: 300px;
border: 1px solid blue;
}
.side-nav { flex-shrink: 0; width: 100px; min-height: 100%; background: grey; }
.main {
padding: 20px;
border: 5px dashed orange;
/* "new code" */
width: 0px;
flex-grow: 1;
}
.scrollable { overflow-x: auto; max-width: 100%; }
.long-content { width: 2000px; height: 50px; background: red; }
<div class='container'>
<aside class='side-nav'>
Aside
</aside>
<main class='main'>
<h1>Test</h1>
<div class='scrollable'>
<div class='long-content'>
This is supposed to scroll horizontally unless your window is super wide
</div>
</div>
<p>Some paragraph below the scrollable box</p>
</main>
</div>
I don't like any of those ideas - but this is life hh.
Question: I am having two div's A & B where DIV A is having min and max width with resize horizontal feature and Div B is auto width.
Now when Div A has 4 divs in it when each div is removed the width of DIVA is auto shrinked but when i dragg div A to right and remove an element in DIV A the width is not auto
.resizeE {
border-right: 6px solid;
display: flex;
align-items: stretch;
justify-content: flex-start;
align-content: center;
width: auto;
min-width: 150px;
max-width: 250px;
height: 100%;
resize: horizontal;
overflow: auto;
}
.E1 .E2 .E3 .E4 {
border: 2px solid #A0A0A0;
width: 50px;
height: 50px;
}
.box {
width: 30px;
float: left;
margin: 5px;
}
.red {
color: red;
background: pink;
}
.blue {
color: blue;
background: light-blue;
}
.green {
color: green;
background: pink;
}
.map {
width: 100%;
}
<div style="height:100%;width:100%;background: #e2e2e2;overflow-y: hidden;overflow-x: hidden;">
<div class="resizeE">
<div class="red box">E1</div>
<div class="red box">E2</div>
<div class="blue box">E3</div>
<div class="green box">E4</div>
</div>
<div class="col p-5">
<div class="map">
block B
</div>
</div>
</div>