Auto scrolling breaking height restrictions - css

broken height
How it looks when overflow: auto is not active
So, I had the height working perfectly as it filled the remaining space of a 100vh app container (blue border line), but when I added overflow: auto to the .action-list and added enough items that it required the overflow to activate suddenly the height is breaking past the app container and pushing past the bottom of the viewport. I have tried every height manipulation of .action-list possible to no avail. I was able to make the whole thing fit perfectly if I changed the .action-container or .action-plate to a smaller percentage of height but that breaks the height to something too small if the overflow: auto is not active. I'm at my wits end.
(.app is in a separate css file. All colored borders are included for reference only.)
.app {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
border: 1px blue solid;
}
.app-container {
margin: 0 0 30px 0;
padding: 0;
box-sizing: border-box;
height: 100%;
width: 100%;
border: 1px solid green;
}
.action-plate {
height: 100%;
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid red;
}
.action-container {
width: 85%;
height: 89%;
background: black; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #9A070E, #9e4676, #f98a2f93); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #4e080b63, #77335a48, #b6662457); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
border-radius: 15px;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between;
box-shadow: 2px 1px 18px rgb(202, 202, 202);
border: 1px thistle solid;
}
.action-list {
width: 100%;
overflow: auto;
box-sizing: border-box;
}
.add-item {
margin: 10px;
box-sizing: border-box;
}

Make your list container flexible with flex-grow so it fills the available space, and change the default min-height: auto to allow the list container to shrink.
Seeing your HTML markup would help in understanding what’s going on here. But it seems like .action-plate is unable to resolve its height: 100%, so it behaves as thought height was auto, which in this case means it will try to size itself based on the height of its content. And that’s why it’s growing so big instead of staying within its 100vh container.
To get the effect you want, you could take advantage of Flexbox properties instead of using percentages.
The header and the tabs should be the size of their content, so we don’t need to do anything extra there.
The container for the list should take up all the remaining space in the app container — not more, and not less. To make sure it grows to fill the available space, we set flex-grow: 1 (by default flex items have flex-grow: 0).
Next, flex items will try to preserve their min-content size by default. This basically means your flex item will try to at least have the size to contain all of its items. This is why it grows beyond the app container.
So instead of its default min-height: auto, we will give it min-height: 0. That means that if you have lots of content, your flex item will no longer try to “protect” its size, and will shrink to fill the size of the container.
Here’s a working example:
body {
margin: 0;
color: white;
}
.app {
display: flex;
flex-direction: column;
height: 100vh;
width: 320px; /* just to illustrate the working example */
height: 480px; /* just to illustrate the working example */
box-sizing: border-box;
background-color: black;
}
header {
text-align: center;
}
.nav-list {
display: flex;
list-style-type: none;
padding: 0;
justify-content: space-evenly;
}
.todo-list-container {
flex-grow: 1;
padding: 16px;
min-height: 0;
overflow: auto;
}
.todo-list-content {
background-color: burlywood;
}
.todo-item {
font-size: 32px;
}
<main class="app">
<header><h1>Exist Better</h1></header>
<nav>
<ul class="nav-list">
<li>Routines</li>
<li>Behaviors</li>
<li>To Dos</li>
</ul>
</nav>
<div class="todo-list-container">
<div class="todo-list-content">
<ul class="todo-list">
<li class="todo-item">Routine 1</li>
<li class="todo-item">Routine 2</li>
<li class="todo-item">Routine 3</li>
<li class="todo-item">Routine 4</li>
<li class="todo-item">Routine 5</li>
<li class="todo-item">Routine 6</li>
<li class="todo-item">Routine 7</li>
<li class="todo-item">Routine 8</li>
<li class="todo-item">Routine 9</li>
<li class="todo-item">Routine 10</li>
</ul>
<button>Add a new routine</button>
</div>
</div>
</main>

Related

Image dissapears when I use flexbox

I am trying to build this nav bar and make it responsive as well, the thing is that when I apply display: flex; the logo just dissapears. For some reason, when I use a fixed width the image stays, but when I use percentages the image just goes away. I would like to use percentages to mantain the responsiveness of the nav bar.
Here is what I have so far.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
header {
display: flex;
border: 10px solid orange;
justify-content: space-around;
width: 100%;
}
header div#company-logo img#header-img {
width: 50%;
}
<header id="header">
<div id="company-logo">
<img src="https://via.placeholder.com/100x50.jpg" alt="hamburguer logo" id="header-img">
</div>
<nav id="nav-bar">
<ul>
<li class="nav-link">Home</li>
<li class="nav-link">Info</li>
<li class="nav-link">Contact Us</li>
</ul>
</nav>
</header>
Like I said before, I have tried with fixed percentages, such as px or vw. I just want to understand why the image dissapears when I use percentages.
#company-logo {
flex: 0 0 auto;
}
...should do it. It means:
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
The important bits are flex-shrink: 0; flex-basis: auto;.

CSS : background-clipping regarding to above elements?

I have this layout on my HTML-page :
page layout
It's a form with checkboxes (which are hidden) and the labels are styled to look like buttons (white border and transparent background to show the gradient below). The gradient part is the container.
Now what I would like to achieve is to show the gradient background only below the buttons so that the parts between the buttons remains white.
See the example here : example (and worship my Photoshop skills)
I tried to figure out a solution but I ended up with nothing. If some of you guys could help me out, I would really appreciate it :)
Thank you in advance !
Create multiple small round boxes with no background and large box-shadow values.
Excess shadow on these boxes will be clipped by overflow: hidden on their respective parents.
Apply gradient background on the outermost parent.
Here is a working demo:
*,
*:before,
*:after {box-sizing: border-box;}
body {
background: linear-gradient(orange, yellow) no-repeat;
margin: 0;
}
.list {
justify-content: center;
list-style: none;
flex-wrap: wrap;
display: flex;
padding: 0;
margin: 0;
}
.list li {
justify-content: center;
padding: 30px;
overflow: hidden;
display: flex;
flex-grow: 1;
flex-basis: 50%;
}
.list .box {
box-shadow: 0 0 0 1000px #fff;
justify-content: center;
align-items: center;
border-radius: 100%;
display: flex;
height: 120px;
width: 120px;
}
<ul class="list">
<li>
<div class="box">Immobilier</div>
</li>
<li>
<div class="box">Travaux</div>
</li>
<li>
<div class="box">Finance</div>
</li>
<li>
<div class="box">Evenementiel</div>
</li>
<li>
<div class="box">Juridique</div>
</li>
<li>
<div class="box">Communication</div>
</li>
<li>
<div class="box">Recrutement</div>
</li>
</ul>

CSS: A header that stays on the screen while the rest of the content scrolls

I'd like scrolling content underneath a variable-height element. Is this a CSS blind spot or am I just not thinking of an obvious solution?
Codepen with my best effort so far, but it only works in Chrome and Firefox:
http://codepen.io/anon/pen/BKpxGP
HTML:
<div class="sidebar">
<header>
<h1>Header content that I would like to remain on the screen even when the main area is scrolled down.</h1>
<p>I want to avoid specifying a height or top padding/margin value, as the content may grow or shrink at times.</p>
<p>This code seems to work in Chrome and Firefox but not in Safari. I haven't tested IE yet.</p>
<p><strong>Challenge:</strong> Can we make it cross-browser?</p>
</header>
<main>
<ul>
<li>Elephant</li>
<li>Giraffe</li>
<li>Otter</li>
<li>Nine-banded armadillo</li>
<li>Cat</li>
</ul>
</main>
</div>
CSS:
.sidebar {
width: 400px;
height: 700px;
border: 10px solid #808080;
margin: auto;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.sidebar header {
background-color: #87ceeb;
border-bottom: 10px solid #00f;
padding: 0 1em;
}
.sidebar header h1 {
font-size: 1.2rem;
}
.sidebar main {
overflow-y: auto;
-webkit-flex-basis: auto;
-ms-flex-preferred-size: auto;
flex-basis: auto;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1;
-webkit-flex-shrink: 1;
-ms-flex-negative: 1;
flex-shrink: 1;
}
.sidebar main li {
height: 400px;
border-right: 10px solid #ffc0cb;
margin: 10px;
padding: 10px;
}
it much more easy than you thought i think.
The css code that you are searching for is:
.example {
position: fixed;
}
On my website you see the same result in the header section. It stays on the top, even if you are scrolling down. :)
I think this is what you want http://codepen.io/dirtysmith/pen/jqyKBO
css
.sidebar header {
background-color: #87ceeb;
border-bottom: 10px solid #00f;
padding: 0 1em;
position: fixed;
width: 368px;
}
added a width to match the container, and position fixed.
I tried this today, and Safari works fine. I guess its Flex support was lagging but it's fixed now. Thank you for the suggestions everyone!

CSS3: Vertically align an element while siblings maintain relative position

I would like to center an element vertically and horizontally. The catch is that any sibling elements should maintain their position relative to the centered element. If the siblings are large enough, they may overflow the viewport. The siblings have variable heights.
I've started a code sample here: https://jsfiddle.net/hqmoz9xy/2/
html,
body {
height: 100%;
}
body {
margin: 0;
padding: 1em;
}
body,
.container {
box-sizing: border-box;
}
.container {
border: 1px solid red;
padding: 1em;
width: 100%;
height: 100%;
}
.main-display {
width: 100px;
height: 100px;
background-color: #999;
padding: 1em;
}
<div class="container">
<div class="main-display">
Main box: this box should be at the center of the container.
</div>
<ul class="extra-info">
<li>These items should naturally follow the main box and not care about vertical centering.</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
This is easily accomplished using JS and negative margins but I would like to do it only with CSS. Is there a way to do this using flex?
You can use flexbox:
.container {
display: flex; /* Magic begins */
flex-direction: column;
}
.before, .after {
flex: 1; /* If possible, center .main vertically */
min-height: 0; /* Really, don't care about overflow, just center .main vertically */
}
.main {
align-self: center; /* Center .main horizontally */
}
html,
body {
height: 100%;
}
body {
margin: 0;
padding: 1em;
}
body,
.container {
box-sizing: border-box;
}
.container {
border: 1px solid red;
padding: 1em;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.before,
.after {
flex: 1;
min-height: 0;
}
.main {
width: 100px;
height: 100px;
background-color: #999;
padding: 1em;
align-self: center;
}
<div class="container">
<div class="before"></div>
<div class="main">
Main box: this box should be at the center of the container.
</div>
<div class="after">
<ul class="extra-info">
<li>These items should naturally follow the main box and not care about vertical centering.</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
</div>
setting negative margin to virtually reduce width down to zero for extra-info, using display:table to shrink on content and and center, you could do something like this :
html,
{
height: 100%;
}
body {
min-height:100%;
border: 1px solid red;
}
body,
.container {
box-sizing: border-box;
}
.container {
padding: 1em;
display: table;
margin: auto;
}
.main-display {
width: 100px;
height: 100px;
background-color: #999;
padding: 1em;
}
.extra-info {
padding:0;
margin:0;
background:lightgray;
margin-right: -50vw;
max-width: 50vw
/* size virtually reduce to zero with equal negative margin value*/
}
<div class="container">
<div class="main-display">
Main box: this box should be at the center of the container.
</div>
<ul class="extra-info">
<li>These items should naturally follow the main box and not care about vertical centering.</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
I am not sure I quite understand what do you want but maybe ?
#main {
width: 100%;
height: 100px;
border: 0px;
display: -webkit-flex;
display: flex;
}
#main div {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
<div id="main">
<div style="background-color:white;">empty</div>
<div style="background-color:Blue;">Your box here</div>
<div style="background-color:white;">empty</div>
</div>
You also can do it with margin only by setting left margin to 40% or 35% depending on your box width

Make flex items stretch full height and vertically center their content

I have a horizontal flex box (i.e. flex-direction: row, i.e. side-by-side) with a few items. Each item can be a single line of text, or can have multiple lines. I want to vertically-align the contents of each flex item.
If each item had a transparent background, I could easily use align-items: center. However, I want each item to be stretched vertically, because I want to set a background (or maybe borders, or maybe it is a clickable region) to the entire available height.
So far, I know:
Stretching: align-items: stretch
Aligning: align-items: center
Stretching and aligning: ???
Demo available at http://codepen.io/denilsonsa/pen/bVBQNa
ul {
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul.second {
align-items: center;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
<ul class="first">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
<hr>
<ul class="second">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
Similar questions:
Question 14012030 and question 23442692 and question 27729619 and question 25311541 ask essentially the same thing, but they either have a single element or plain text as child of each flex item. As soon as we have mixed content, possibly with multiple elements, those solutions do not work.
Question 19026884 is unrelated, the issue there was the wrong markup.
Unfortunately, it is impossible to achieve the desired effect while using the exact markup posted in the question.
The solution involves:
Setting display: flex; on <li>.
Wrapping the <li> contents into another element.
This is required because <li> is now a flex container, so we need another element to prevent the actual contents from becoming flex items.
In this solution, I introduced a <div> element, but it could have been other element.
Now that <li> is a flex container and it contains only a single child, we can use align-items and/or justify-content to align this new and only child.
The DOM tree looks like this:
<ul> flex-parent, direction=row
├ <li> flex-item && flex-parent && background && JavaScript clickable area
│ └ <div> flex-item as a single transparent element
│ ├ Actual contents
│ └ Actual contents
├ …
Note: The solution in this answer uses 2 nested flex boxes. The solution by Michael_B uses 3 nested flex boxes, because it has the added challenge of expanding the <a> element to fill the entire <li>. Which one is preferred depends on each case. If I could, I would accept both answers.
/* New code: this is the solution. */
ul > li {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* Old code below. */
ul {
display: flex;
flex-direction: row;
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
button:focus + ul {
font-size: 14px;
width: auto;
}
<button>Click here to set <code>width: auto</code> and reduce the font size.</button>
<!-- New code: there is a single <div> between each <li> and their contents. -->
<ul>
<li><div>Sample</div></li>
<li><div><span>span</span></div></li>
<li><div><span>multiple</span> <span>span</span></div></li>
<li><div>text <span>span</span></div></li>
<li><div>multi<br>line</div></li>
</ul>
I want each item to be stretched vertically, because I want to set a
background (or maybe borders, or maybe it is a clickable region) to
the entire available height.
You can achieve this layout without any changes to your HTML structure. There's no need for additional containers.
You already have a primary flex container and a group of flex items. Simply make those flex items into nested flex containers. That will enable you to align the content with flex properties.
(Since you mentioned that you may need clickable regions, I switched from li to a elements.)
nav {
display: flex;
background: #CCF;
width: 25em;
}
nav > a {
flex: auto; /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
text-align: center;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
}
nav > a:nth-child(2) {
background: #CFC;
}
html, body {
font-family: sans-serif;
font-size: 25px;
}
<nav>
Sample
<span>span</span>
<span>multiple</span> <span>span</span>
text <span>span</span>
multi<br>line
</nav>
revised codepen
Note that content placed directly inside a flex container is wrapped in an anonymous flex item:
From the spec:
4. Flex Items
Each in-flow child of a flex container becomes a flex item, and each contiguous run of text that is directly contained inside a flex
container is wrapped in an anonymous flex item.
So, because the text is automatically wrapped in flex items, you can keep the full height of each item (align-items: stretch from the primary container) and vertically center the content (align-items: center from the nested containers).
Make the li flex-containers with flex-direction:column. I think that's what you are after.
html,
body {
font-family: sans-serif;
font-size: 25px;
}
ul,
li {
list-style: none;
margin: 0;
padding: 0;
}
ul {
background: #CCF;
width: 25em;
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
/*outline: 1px dotted #444;*/
}
ul > li:nth-child(2) {
background: #CFC;
}
<ul class="first">
<li>Sample</li>
<li><span>span</span>
</li>
<li><span>multiple</span> <span>span</span>
</li>
<li>text <span>span</span>
</li>
<li>multi
<br>line</li>
</ul>
Flex-child items can also be flex-parent items.
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-family: sans-serif;
font-size: 25px;
}
body {
display: flex;
flex-flow: column nowrap;
background-color: #333;
overflow: hidden;
}
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.List {
padding: 0;
margin: 0;
background: #CCF;
width: 25em;
list-style: none;
display: flex;
flex-flow: row nowrap;
justify-content: center;
}
.ListItem {
flex-basis: 5em;
display: flex;
flex-flow: row wrap;
text-align: center;
align-items: center;
}
.ListItem:nth-child(2) {
background: #CFC;
}
.ListItem__content {
width: 100%;
}
<ul class="List">
<li class="ListItem">
<span class="ListItem__content">Sample</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multiple <br> span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multi<br>line</span></li>
</ul>

Resources