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).
Related
Hi I have a CSS question.
There are two columns, the right (B) column has a fixed width of 100px, and the left (A) column have to fill the remaining width. Also, inside A column, there is a list of child components that are added horizontally.
The problem is, when the child component is added, A column's width becomes longer and column B goes down.
How can I make it so that when a child component is added, if it exceeds A column width, it is added to the bottom line inside A column?
When the number of child elements is small
When the number of child elements increases (AS-IS)
When the number of child elements increases (TO-BE)
Use flex-wrap on both the overall container and on A, and set the width of box A to be calc(100% - 100px).
body {
width: 100vw;
padding: 0;
margin: 0;
color: white;
}
#flex {
display: flex;
background-color: grey;
width: 100vw;
height: fit-content;
flex-wrap: wrap;
}
#a {
width: calc(100% - 100px);
height: fit-content;
background-color: red;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
#a .x {
width: 100px;
margin: 10px;
background-color: green;
height: 200px;
}
#b {
width: 100px;
height: 500px;
background-color: blue;
}
<div id="flex">
<div id="a"> A
<div class="x">X</div>
<div class="x">X</div>
<div class="x">X</div>
</div>
<div id="b">
B
</div>
</div>
with 1 'X' div (ignore alignment, is because of the 'A' text;
with 4 'X' divs:
Instead of flex you can use display grid. With grid you can define if an item should be dynamic or static.
Example:
.main {
display: grid;
grid-template-columns: 1fr 100px;
}
<div class="main">
<div class="dynamic-size">
I am dynamic in size
</div>
<div class="static-size">
I'll always be 100px
</div>
</div>
The 1fr in grid-template-columns stands for one free space, meaning all the space besides the 100px of the second element will be filled by the first item.
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'm trying to create a table which will be responsive,
but to make it simple I want to make it scroll horizontally when it has too many columns.
.fixed-table-wrap {
display: flex;
flex-wrap: wrap;
overflow: hidden;
}
.fixed-column {
width: 140px;
}
.standard-column {
width: calc(100% - 140px);
overflow-x: auto;
}
.sc-content {
display: flex;
flex-wrap: wrap;
min-width: 1485px;
width: 100%;
}
<div class="fixed-table-wrap">
<div class="fixed-column">
<div class="fc-content">
</div>
</div>
<div class="standard-column">
<div class="sc-content">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</div>
In order to have the scroll effect I have to use min-width or a fixed width, but I don't want that because I want the table to be responsive, when it is not exceeding the window's width it should just be natural, and when it exceeds, it scrolls.
To get an even better idea of what my problem is:
What my table looks like:
More of what my table looks like:
What happens when I remove the min-width:
What happens when I have less content WITH min-width:
What happens when I have less content WITHOUT min-width:
Try using the CSS overflow-x property and set an element you've wrapped around your table to "scroll". So with HTML like this:
<div id="table-wrapper">
<table>
<!-- table content here -->
</table>
</div>
And CSS like this:
<style type="text/css">
#table-wrapper {
width: 100%;
x-overflow: scroll;
}
</style>
I've found my solution:
.fixed-table-wrap {
display: flex;
flex-wrap: wrap;
overflow: hidden;
width: fit-content;
}
.fixed-column {
width: 140px;
}
.standard-column {
width: calc(100% - 140px);
overflow-x: auto;
}
.sc-content {
display: flex;
flex-wrap: wrap;
width: max-content;
}
.child {
width:140px;
}
I have a simple HTML document. I have a header, a section and a div (that contains an unknown number of other divs).
The header and the section do not (and can not) have set heights. Their height comes from the content. Only their width is known (set to 100%).
Is it possible, with flexbox or other means, to get each of those child divs, in this case with class="fill" to be the height of the body - minus the header and section?
In other words, when someone goes to the page, I want them to see the header and the section and then have the first div.fill reach all the way to the bottom, forcing them to scroll to see the next div (but not scroll to see the bottom of the first child div).
I am using a templating system so unfortunately the structure of the HTML can not change and I would like to do this only in CSS.
<html>
<body>
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="container">
<div class="fill">I Want</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</div>
</body>
</html>
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
}
.container {
flex: 1; /* 1 */
display: flex;
flex-direction: column;
overflow-y: scroll;
}
.fill { flex: 0 0 100%; } /* 2 */
header { background-color: aqua; }
section { background-color: orange; }
.fill:nth-child(odd) { background-color: yellow; }
.fill:nth-child(even) { background-color: lightgreen; }
<body>
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="container">
<div class="fill">I Want</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</div>
</body>
jsFiddle
Notes:
The flex-grow: 1 component of flex: 1 tells the .container element (a flex item child of body) to consume all remaining space. This will cause .container to use up any space not consumed by header and section.
The flex-basis: 100% component of flex: 0 0 100% tells the .fill items (flex item children of .container) to consume 100% height of the parent. So these items will always take the full height of flex-grow: 1 on the parent.
Because flex items are set, by default, to shrink in order to not overflow the container, an override is set with flex-shrink: 0 in the flex: 0 0 100% rule. This disables the shrinking feature and allows the items to stay fixed at 100% height. (Otherwise, regardless of the defined height / flex-basis, the items would shrink evenly to prevent an overflow. See demo.)
If you change the structure of the elements a bit you can get it with only css.
Basically add the first .fill element in a container with the header and the section (let's call it first). For the other divs use height: 100vh
body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.fill {
height: 100vh;
overflow: auto;
}
.first {
flex: 1;
}
header { background-color: aqua; }
section { background-color: orange; }
.first, .fill:nth-child(odd) { background-color: yellow; }
.fill:nth-child(even) { background-color: lightgreen; }
<html>
<body>
<div class="container">
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="first">I Want</div>
</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</body>
</html>