Fill available height, then scroll when no more room - css

I would like two elements (divs) in a column. The first has a fixed height, and the second I want to fill all remaining height. If the content of the second element exceeds the space left, I want to scroll its contents, and not have the second element take up more space (which causes the parent to scroll).
Image (current)
For example, the "first element" is the search bar in this photo. Fixed height, and remains on top.
The "second element" is the data table. As you can see at the bottom, the table contents extend the height of the page, and the entire page becomes scrollable. This is not what I am looking for.
Image (desired) I would like the table container to behave similarly to this red box. It fills it's remaining height, and when it contains content that overflows, I would like just that element to scroll. Only scroll the content within the confines of the red box.
I have seen many examples similar to this, but all of them have a specified height for the "second element", even if it is a vh property. vh doesn't work for me since the 100% isn't the entire viewport.
I've been using flexbox to try and achieve this, and I get close, but I've only ever been able to either specify a height for the "second element", or have it grow to fill available space, but then exceed it, and overflow the whole container.
The below code is very close to desired behavior, except when the viewport becomes to small, "box 2" goes off screen and the whole thing scrolls, I want the content in "box 2" to scroll.
html,
body {
height: 100%;
}
.container {
height: 100%;
min-height: 100%;
display: flex;
flex-direction: column;
.box {
text-align: center;
color: white;
font-family: sans-serif;
font-size: 36px;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: center;
}
.box-1 {
background-color: green;
height: 60px;
}
.box-2 {
background-color: blue;
flex: 1;
}
<div class="container">
<div class="box box-1">box 1</div>
<div class="box box-2">box 2</div>
</div>

Just apply an overflow:auto on the second div and a max-height to the container.
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.container {
max-height: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.box {
text-align: center;
color: white;
font-family: sans-serif;
font-size: 36px;
padding: 20px;
justify-content: center;
}
.box-1 {
background-color: green;
height: 60px;
}
.box-2 {
background-color: blue;
flex: 1;
overflow: auto;
}
.expando {
height: 1000px;
/* for demo */
}
<div class="container">
<div class="box box-1">box 1</div>
<div class="box box-2">box 2
<div class="expando"></div>
</div>
</div>

html,
body {
height: 100%;
margin: 0;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.box {
text-align: center;
color: white;
font-family: sans-serif;
font-size: 36px;
padding: 20px;
}
.box-1 {
background-color: green;
height: 60px;
}
.box-2 {
background-color: blue;
height: 100%;
overflow: auto;
}

Related

Vertical align text to top of a div on Flexbox

I have a flex div with a div and a span, structure that I don't want to modify.
.Flex {
display: flex;
background: lightgray;
height: 300px;
}
.Square {
width: 30px;
height: 30px;
background: black;
}
.Text {
font-family: "Arial";
font-size: 40px;
background: tan;
}
<div class="Flex">
<div class="Square"></div>
<span class="Text">Title</span>
</div>
I'm trying to align the top of the "T" of the text with the top of the Flex div, something like the following image:
But I cant. align-content: flex-start will align all children to the top, but the text within the span will still have some distance to the top of the div.
How is possible to achieve this?
Add one property to your text's css: (you can modify this value according to the positioning of the text you would like, the higher, the more space the text has from the top edge)
line-height: 0.75;
.Flex {
display: flex;
background: lightgray;
height: 300px;
}
.Square {
width: 30px;
height: 30px;
background: black;
}
.Text {
font-family: "Arial";
font-size: 40px;
background: tan;
line-height: 0.75;
}
<div class="Flex">
<div class="Square"></div>
<span class="Text">Title</span>
</div>

CSS: flex-grow maintain vertical aspect ratio

I am creating a website with a circular menu. The website content should fit all onto the homepage without the need to scroll. The menu needs to fill the remaining space on the homepage. However, I am unsure how to maintain the shape of the circle while filling the remaining space on the homepage using flex-grow: 1. Is there a way I can do this with pure CSS? Setting the menu to a set viewport size is not acceptable, it needs to fill the remaining space. I am not having luck using the traditional padding-top: 100% to maintain aspect ratio. The circle is not quite circular and it takes up twice the remaining space.
body {
height: 100vh;
display: flex;
flex-direction: column;
margin: 0;
}
#title {
font-size: 30px;
}
#circle {
background: black;
border-radius: 50%;
flex-grow: 1;
padding-top: 100%;
}
#footer {
background: black;
color: white;
}
<body>
<div id="title">Title</div>
<div>navigation</div>
<div id="circle"></div>
<div id="footer">Footer</div>
</body>
Edit
I have figured out a way to maintain the aspect ratio of the circle filling the remaining space with flex grow. However, it is what I would consider a hack so I am leaving this question open.
body {
height: 100vh;
display: flex;
flex-direction: column;
margin: 0;
}
#title {
font-size: 30px;
}
#circle {
background: black;
border-radius: 50%;
flex-grow: 1;
/*width: max-content;*/
padding: 0%;
align-self: center;
}
#circle img {
height: 100%;
width: auto;
justify-content: center;
}
#footer {
background: black;
color: white;
}
<body>
<div id="title">Title</div>
<div>navigation</div>
<div id="circle"><img src="https://luxury.zappos.com/search/imgs/blank.20190219170746.png"></div>
<div id="footer">Footer</div>
</body>
Edit 2
It seems I was mislead by caniuse.com. This solution does not seem to work in most browsers besides chrome. Is there another solution?
Put the circle div inside a wrapper div in your HTML:
<div id="circle-wrap">
<div id="circle"></div>
</div>
Then move the flex rule to the wrapper:
#circle-wrap {
flex-grow: 1;
}
body {
height: 100vh;
display: flex;
flex-direction: column;
margin: 0;
}
#title {
font-size: 30px;
}
#circle-wrap {
flex-grow: 1;
}
#circle {
background: black;
border-radius: 50%;
padding-top: 100%;
}
#footer {
background: black;
color: white;
}
<body>
<div id="title">Title</div>
<div>navigation</div>
<div id="circle-wrap">
<div id="circle"></div>
</div>
<div id="footer">Footer</div>
</body>

Sidebar with two flexbox navs top and bottom

I´m trying to align two navigations inside a sidebar –with 100% viewport height – by use of flexbox.
the red box should be placed on the top of it´s sidebar parent
the blue box on the bottom.
In case the red navigation grows and the space between both is to little the sidebar should be scrollable in y-axis. What I´ve tried is setting top and bottom margin for both without luck. Can somebody help me out ?
Thanks!
html, body {
margin: 0;
}
* {
box-sizing: border-box;
}
.sidebar {
height: 100vh;
width: 300px;
background: #ccc;
padding: 10px;
overflow-y: scroll;
}
.sidebar__top {
background: red;
height: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.sidebar__bottom {
background: blue;
height: 100px;
margin-top: auto;
}
<aside class="sidebar">
<nav class="sidebar__top"></nav>
<nav class="sidebar__bottom"></nav>
</aside>
Here is my fiddle: http://jsfiddle.net/1dw7h2sp/1/
There are probably other ways to do this. In short I did the following:
Wrap your elements with a parent that is able to grow in size (.sidebar__wrapper)
Set the min-height instead of height so it can grow
Use flex-grow if you want an element to fill out the remaining space.
html, body {
margin: 0;
}
* {
box-sizing: border-box;
}
.sidebar {
height: 100vh;
width: 300px;
background: #ccc;
overflow-y: scroll;
margin: 0;
padding: 0;
}
/* set up a wrapper that can grow in size */
.sidebar__wrapper {
height: auto;
min-height: 100vh;
width: 100%;
background: #808080;
padding: 10px;
margin: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.sidebar__top {
background: red;
min-height: 200px;
margin-bottom: 10px;
/* this fills up the remaining space */
flex-grow: 1;
}
.sidebar__bottom {
background: blue;
min-height: 100px;
}
<aside class="sidebar">
<div class="sidebar__wrapper">
<nav class="sidebar__top" contenteditable="true">
<p>test</p>
</nav>
<nav class="sidebar__bottom"></nav>
</div>
</aside>

Center text in 100%-screen-width div in small wrapper

I want to center a div and it's text, in a 100%-screen-width div, which is in a smaller wrapper.
.wrapper {
height: 800px;
width: 900px;
margin: auto;
background-color: #000000;
}
.box-wrapper {
width: 1000%;
position: relative;
left: -500%;
background-color: #FF6600;
}
.box {
background-color: #FF0000;
width: 600px;
position: relative;
left: 50%;
color: #00FF00;
}
span {
text-align: center;
display: block;
}
<div class="wrapper">
Random text for wrapper-div
<div class="box-wrapper">
<div class="box">
<span>ABC</span>
<span>DEF</span>
<span>GHI</span>
</div>
</div>
</div>
This code is kind of working but not perfect.
The red div should be moved a bit to the right, also the way
of doing it is not the best in my opinion.
I want a more robust and responsive solution.
To be more clear, it's for the pink division on the bottom
of this website: http://ndvibes.com
There the code is working 99% of the times and reponsive. But on some computers/screens it's 50% off. So I want a less-hacky (without transform etc) and more standard, robust way of getting that effect.
Wrapper 900px > 100%-screen-width coloured div > Centered text in that coloured div.
How can I achieve this the best as possible?
Thanks!
How about this approach, using absolute positioned pseudo elements. The outer-space div with overflow:hidden is to prevent a horizontal scroll bar appearing. I have added padding-top to the .wrapper just so you can see the snippet running in full screen mode.
body {
margin:0;
}
.outer-space {
overflow: hidden;
padding-top:80px;
}
.wrapper {
height: 800px;
width: 100%;
max-width: 900px;
margin: auto;
background-color: #000000;
}
.box {
background-color: #8904B1;
margin:0 auto;
color: #ffffff;
position: relative;
z-index: 2;
padding:10px 0;
}
.box-wrapper {
position: relative;
width:100%;
max-width: 600px;
margin:0 auto;
}
.box-wrapper:before, .box-wrapper:after {
content:"";
position: absolute;
height:100%;
width:100vw;
background-color: #8904B1;
top: 0;
z-index: 1;
}
.box-wrapper:before {
left:-100%;
}
.box-wrapper:after {
right:-100%;
}
span {
text-align: center;
display: block;
}
<div class="outer-space">
<div class="wrapper">
Random text for wrapper-div
<div class="box-wrapper">
<div class="box">
<span>Crazy full width window</span>
<span>absolute positioned pseudo elements</span>
<span>with centered content div and centered text thingy</span>
<span>all inside of a fixed width page wrapper!</span>
<br><span>““”̿ ̿ ̿ ̿ ̿’̿’̵͇̿̿з=(•̪●)=ε/̵͇̿̿/̿ ̿ ̿ ̿ ̿’““</span>
</div>
</div>
</div>
</div>
To center child element, add the following to the parent wrap will center all child.
display: flex;
align-items: center;
justify-content: center;
If you want 100% screen width, use viewport (100vw) for 100% screen width
viewport
The #viewport CSS at-rule contains a set of nested descriptors in a CSS block that is delimited by curly braces. These descriptors control viewport settings, primarily on mobile devices.
1vw = 1% of viewport width
1vh = 1% of viewport height
1vmin = 1vw or 1vh, whichever is smaller
1vmax = 1vw or 1vh, whichever is larger
REF: #viewport
REF: Viewport Sized Typography
body {
margin: 0;
}
.wrapper {
height: 800px;
width: 900px;
margin: auto;
background-color: #000000;
}
.box-wrapper {
width: 900px;
max-width: 900px;
position: relative;
background-color: #FF6600;
display: flex;
align-items: center;
justify-content: center;
}
.outer-wrapper {
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
}
.box {
width: 80%;
background-color: #FF0000;
position: relative;
color: #00FF00;
}
span {
text-align: center;
display: block;
}
<div class="outer-wrapper">
<div class="wrapper">
<p>Random text for wrapper-div</p>
<div class="box-wrapper">
<div class="box">
<span>ABC</span>
<span>DEF</span>
<span>GHI</span>
</div>
</div>
</div>
</div>

Scrollable paragraph having limited height to its parent

I want to make P to be able to take more text than the height can contain, just so the text can be scrolled down to be read. DIV CLASS="others" has the right height I want. (500px)
The problem is, when I use the overflow: scroll function it goes all the way to the bottom of the page.
EDIT: Forgot to mention I want the titles "News" and "Products" to be without the scroll bar.
Thanks.
.others {
position: relative;
vertical-align: middle;
width: 70%;
background-color: #d0d0d0;
height: 500px;
margin: 0px;
padding: 40px 15% 20px 15%;
display: flex;
justify-content: center;
}
.others div {
width: 400px;
display: inline-block;
float: left;
margin: 0px 15px;
}
.others #news {
background-color: black;
color: white;
text-align: center;
}
.others #products {
background-color: black;
color: white;
text-align: center;
}
.others a {
color: white;
text-decoration: none !important;
}
.others #newsfeed, #productsfeed {
margin: 0px;
padding: 10px 0px;
background-color: lightgreen;
}
.others p {
margin: 0px;
padding: 10px 10px;
vertical-align: middle;
height: 800px;
overflow: scroll;
}
<DIV CLASS="others">
<DIV ID="news">
<H3 ID="newsfeed">News</H3>
<P>News will come here.</P>
</DIV>
<DIV ID="products">
<H3 ID="productsfeed">Products</H3>
<P>Cool photos here.</P>
</DIV>
</DIV>
As I mentioned in my comment, the issue is caused by specifying an explicit height to the inner paragraphs.
Besides, in order to make the inner paragraphs respect the height of their parents (#news and #products flex items which have the same height of their flex container, the .other) you could change the display type of the parents to flex as well and set their flex-direction to column.
And then give flex: 1; to the paragraphs as follows:
Example Here
#news, #products {
display: flex;
flex-direction: column;
}
#news p, #products p {
flex: 1;
overflow: auto; /* up to you */
}
As a side-note: make sure you have included the old (prefixed) syntax of flexbox as well for the sake of browser support. You could use tools like Auto Prefixer to achieve that.
You need a containing div on the paragraphs, then set overflow: scroll; and height: 460px; on that container (or whatever height you need to have it contained within the 500px tall .others block).
You'd also need to make sure your .others div styling doesn't apply to that container - in my example below, I changed that selector to .others > div to only select immediate children of .others. And you should remove the height: 800px; from the inner paragraphs, as mentioned by Hashem Qolami.
jsfiddle example

Resources