I'm having trouble using CSS3 flex display and overflow.
I'd like a box to be "y-scrollable" if contents overflow on y-axis and "x-overflowed" if content overflows on x-axis.
I found this codepen illustrating how to set the box y-scrollable and I forked this one to illustrate my problem.
As you can see (using Chrome), a x-scrollbar is added even if overflow-x is set to visible. I hoped content would overflow upon the y-scrollbar and be visible without x-scrollbar...
Any solution ?
The base HTML code is
<ul>
<li><div>Item</div></li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
The base CSS code is
ul {
flex: 1;
min-height: 0;
overflow: auto;
}
And, to make trouble, replace by
ul {
flex: 1;
min-height: 0;
overflow-x: visible ;
overflow-y: auto;
}
div{
background-color : red ;
width : 150% ;
}
For make it really revealant, add
ul {
list-style: none;
margin: 0;
padding: 0;
background: hsl(200,100%,90%);
}
li { padding: 20px; }
li:nth-child(odd) { background: hsl(200,100%,85%); }
header, footer { padding: 20px; background: hsl(0,0%,70%); }
body {
display: flex;
/* doesn't work without prefix */
-webkit-flex-flow: column;
flex-flow: column;
height: 100%;
box-sizing: border-box;
padding: 20px;
background: hsl(0,0%,80%);
}
html { height: 100%; }
I could be reading this wrong, but if you're not wanting there to be a horizontal scroll bar, then you can set overflow-x: hidden; and it should be okay.
Related
I'm trying to create a sidebar which has 2 boxes. Each box can contain any number of list items(could be hundreds of items), but it's likely that the first will contain only a few items, and the second will contain many more.
I have the following (created in ReactJS):
<div class="drawer">
<div class="drawerContainer">
<div class="sideboxWrapper">
<SideBox header="Box 1" />
<SideBox header="Box 2" />
</div>
</div>
</div>
Each SideBox generates the following structure:
<div class="sidebox">
<h2 class="boxheader">{header}</h2>
<div class="boxContent">
<ul class="sideboxList">
<li class="listItemText listItemTextCurrent">Item 1</li>
<li class="listItemText listItemTextCurrent">Item 2</li>
... more items ...
</ul>
</div>
</div>
So, first of all, I want the boxes to fill the sidebar, but not overflow it. If the boxes are short enough to both fit, then they should both take up as much space as they need, and any remaining space is left blank. If they don't both fit, then they should take up the available space, and the boxContent div should become scrollable.
.drawer {
flex: 0 0 240px;
height: 100%;
overflow-y: hidden;
padding: 10px 0;
}
.drawerContainer {
height: inherit;
overflow: hidden;
padding-bottom: 10px;
padding-top: 10px;
}
.sideboxWrapper {
display: flex;
flex-direction: column;
height: inherit;
overflow: hidden;
}
.sidebox {
margin: 10px;
padding: 0px;
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
}
.boxContent {
overflow-y: auto;
}
The problem I'm having is that when one of the lists is very long, the sideboxes just expand to fit it, even if that means going outside the sideboxWrapper (the overflow is hidden, so the part of the sidebox outside the sideboxWrapper can't be read). What I want to happen is that the flex layout arranges the sideboxes to fit inside the sideboxWrapper, and then the boxheaders are shown and the boxContent is resized (with scrollbars) to fit within the remaining space. So, a long list will have scrollbars.
How can I achieve this?
here is what could be your CSS , I added border so you can see where stands some of your boxes. Using flexbox on so many levels requires to follow clearly what you are doing and see where flex is avalaible and needed.
* {
box-sizing: border-box;
}
.drawer {
width: 240px;/* without a flex parent that works too */
height: 100vh;/* example for a full screen height */
overflow-y: hidden;
padding: 10px 0;
border: solid;
}
.drawerContainer {
height: 100%;
padding-bottom: 10px;
padding-top: 10px;
}
.sideboxWrapper {
display: flex;
flex-direction: column;
height: 100%;
border: solid green;
overflow: hidden;
}
.sidebox {
margin: 10px;
padding: 0px;
flex-basis: 50%;/* make it half */
display: flex;
flex-direction: column;
min-height: 0;/* what is needed */
}
.boxContent {
flex-grow: 1;
overflow-y: auto;
}
So I am learning a bit more about using CSS flex instead of using static positioning of content. However, I have defined my link styles as well as bold styles. My guess is that it's adapting to the container that is in (which is using flex feature) and that is why it is stretching across the size of the container it is inside. My question now is, how do I fix this? I've seen that I can do "display:inline-block" on the link, but that has not fixed it.
Here is my code:
.container{
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
width: 80%;
margin: auto;
background-color:#fff;
overflow: hidden;
font-size: 15px;
line-height: 20px;
padding:1em;
}
.container > * {
padding: 15px;
-webkit-flex: 1 100%;
flex: 1 100%;
}
a{
text-decoration:none;
border-bottom-style:double;
border-bottom-width:2px;
color:#99d3df;
display:inline-block;
padding:0px;
overflow: hidden;
}
i{
display:inline-block;
color:#88bbd6;
text-decoration:italic;
}
And what I have:
This is a Google Link<BR>
Google is <i>extremely helpful</i>!
This is what it looks like for reference.
Problem image
It seems you missed the .container wrapper div in the markup you provided.
Let's look at this code:
<!-- HTML -->
<div class="container">
<span>This is a </span><a href="http://google.com">Google Link</a
</div>
<div class="container">
<span>Google is </span><i>extremely helpful</i>!
</div>
<!-- /HTML -->
/* CSS */
.container > * {
padding: 15px;
-webkit-flex: 1 100%;
flex: 1 100%;
}
Property flex with value of 1 100% means we tell the browser to style any elements (the asterisk *) nested in .container to have 100% width of their parent's width.
I would suggest you to just remove that part to fix the problem.
Here's my approach to your markup.
.container {
display: flex;
width: 80%; /* flexible value */
flex-direction: row; /* this is to make sure that we'll have side-to-side layout within .container */
}
a {
text-decoration: none;
border-bottom-style: double;
border-bottom-width: 2px;
color: #99d3df;
display: inline-block;
padding: 0px;
}
a, i{
margin-left: 5px; /* this is to give a 10px spacing */
}
<div class="container"><span>This is a </span>random link<span></span></div>
<div class="container"><span>Google </span><i>is extremely helpful! </i></div>
It is working fine when I tried your code in js fiddle
see in this image
May be some other css is affecting your links to stretch it out.
On a simple flex-box layout, I am trying to align nav items to the end of the first (left) side-bar. My first thought was to recreate the aside main aside layout with :before element :after so the nav items would always align to the sidebar, but I can't seem to get the :before and :after elements to match the size of each aside. Here is an example of what I am trying to do
Flex Example
And here is the current code I am using
http://codepen.io/anon/pen/GoJEbX?editors=010
I wouldn't be using flex-wrapping rows here. It makes sense to start with flex-direction:column to get the full 100% height and then put the middle content (main and aside elements) in their own flex-container which can then grow as much as is required.
The horizontal layout is all flexbox.
Based on the original code the aside are 1/12th wide each (flex:1) while the main is 10/12ths (flex:10).
Therefore to line up the menu with the main, the menu itself needs to be shifted over the same amount (which means it's 11/12ths [flex:11] so the pseudo-element is just flex:1.
Adjust as required.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
min-height: 100%;
}
.wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
nav {
display: flex;
}
nav:before {
content: '';
flex: 1;
background: plum;
/* for reference */
}
nav ul {
display: flex;
background: blue;
list-style-type: none;
flex: 11;
}
nav ul a {
display: block;
padding: 20px 20px 0 0;
color: white;
text-decoration: none;
}
.content {
flex: 1;
display: flex;
}
main {
background: red;
flex: 10;
}
aside {
background: green;
flex: 1;
}
footer {
background: yellow;
}
<div class="wrapper">
<header>
<nav>
<ul>
<li>Item 1
</li>
<li>Item 2
</li>
<li>Item 3
</li>
</ul>
</nav>
</header>
<div class="content">
<aside>Sidebar 1</aside>
<main>Main Content Area</main>
<aside>Sidebar 2</aside>
</div>
<footer>Footer</footer>
</div>
Codepen Demo
I have the following construct to render a simple layout with fixed header and footer and a flexible body that with scrollable content: http://jsbin.com/jokevuyave/1/edit?html,css
<div id="main-view">
<div class="rows">
<div class="head">header</div>
<div class="main scroll"></div>
<div>footer</div>
</div>
</div>
and this are the styles:
.rows,
.columns {
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.columns {
flex-direction: row;
max-height: 100%;
overflow: hidden;
}
.main {
flex: 1;
}
.scroll {
display: flex;
overflow: hidden;
position: relative;
flex-direction: column;
}
.scroll > * {
margin: 0;
width: 100%;
overflow: auto;
}
html,
body,
#main-container,
#main-view,
.scrollable {
height: 100%;
margin: 0
}
#main-view > div {
max-height: 100%;
display: flex;
}
.head {
height: 120px
}
This construct works well in firefox and also in chrome until the version 43 was released. Now the height of the containers is wrong, header and footer don't expand to display its content and the content container lays over the header content. Any idea how to fix this?
Edit
The problem seems to be this line:
#main-view > div {
max-height: 100%;
}
The idea is that the box should only expand if the content is to large.
Change it to
#main-view > div {
height: 100%;
}
fix the wrong height for the inner container but now the box has always the height of 100%, even if the content is really small.
There is a problem with max-heigth and flexbox: flexbox misbehaving with max-height
So the solution is to set the flex property to every element insight rows container to 0
.rows .main {
flex: 1;
}
.rows > * {
flex: 0 0 auto
}
I have an html page structure like this:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
.............
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
On this page, I want all list element to have the same width - I don't care about the content, only the color is really important in this case - and I want all thos elements to fit in their parent div (#list) when the page just loaded, this mean no scroll.
And this list is not final, I can add or delete somme elements in my list after the page load. I would like to know if there is a CSS way to get this result, JavaScript is not really suitable in this case.
Is that possible ?
You can achieve this kind of behavior by using flex:
HTML structure:
<div id="list">
<ul>
<li style="background-color:orange;">Lorem</li>
<li style="background-color:black;">Lorem</li>
...
<li style="background-color:blue;">Lorem</li>
</ul>
</div>
CSS:
#list {
border-style: solid;
border-width: 3px;
white-space: nowrap;
}
#list ul {
display: flex;
flex-direction: row;
margin: 5px;
padding: 0;
}
#list ul li {
border-style: solid;
height: 50px;
list-style-type: none;
}
Here is a working demo: http://jsfiddle.net/kmbxawdd/1/
Yes, you can use flexible boxes:
#list {
display: flex; /* Magic begins */
border: 3px solid;
padding: 1em;
}
#list > li {
width: 0; /* Ignore the width of the content */
flex-grow: 1; /* Distribute remaining space equally */
overflow: hidden; /* Hide possible overflow */
height: 50px;
border-style: solid;
}
<ul id="list">
<li style="background-color:orange;">Lorem</li>
<li style="background-color:red;">Lorem</li>
<li style="background-color:black;">Lorem</li>
<li style="background-color:blue;">Lorem</li>
</ul>
JSFiddle Example
Flexbox is your friend.
div#list {
height: 800px; /*Whatever you want, really*/
width: 800px; /*Again, substitute this with whatever size you like*/
}
div#list ul {
height: 100%;
width: 100%;
display: flex;
flex-flow: row nowrap;
align-content: stretch;
list-style: none;
padding: 0;
margin: 0;
}
div#list ul li {
-webkit-flex: 0 1 100%;
flex: 0 1 100%;
}
You can try to set display to "table" on list and "table-cell" on li. But it will work as you expect only if all li elements will contain content with same width. And list itself must have explicitly defined width, of course.