Looking to have one large item on the left and a lot of small items on the right. If the browser window is big enough, I'd like the small items to "float" in a columnar manner such that they don't exceed the height of the large item. However, when the browser shrinks, I'd like the small items to wrap down below the large one in a single row.
Here's a codepen to demonstrate: https://codepen.io/anon/pen/WXQdEN
div.container {
display: flex;
flex-wrap: wrap;
}
div.right-variable {
max-height: 320px;
align-items: center;
}
div.test-700 {
width: 700px;
height: 320px;
background: green;
color: #ffffff;
font-size: 40px;
}
div.test-100 {
width: 100px;
height: 100px;
background: red;
outline: 1px solid black;
margin: 2px;
float: left;
}
<table>
<tr>
<td>
<div class="test-700">Example Table</td>
</td>
<td>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
</td>
</tr>
</table>
<div class="container">
<div class="left-fixed">
<div class="test-700">Non-Working Flex</div>
</div>
<div class="right-variable">
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
</div>
</div>
The table shows the desired behavior of the red boxes at large resolutions. As the browser shrinks, the boxes float around to fill the space.
But when the browser gets too small to contain them, I want the flex behavior where the red boxes wrap down under the green one. I understand that this doesn't work because I can't float the items within the flex, but I don't understand how to achieve a similar behavior without float. I'd like to achieve this using flex and CSS only. Is that possible?
Thank you for any assistance.
The main issue here is related to sequence for wrapping and since the browser don't know which to wrap before the other, they start with the outer element.
Also, there is no property that one can set, to define the order, but there is media query, where we can set a breaking point, and in this case, use it to tell when the container is allowed to wrap.
Remove flex-wrap: wrap from the container and add it back at a desired maximum width using a media query.
Then also make the div.right-variable a flex container and have the red elements centered.
Stack snippet
div.container {
display: flex;
}
div.right-variable {
margin: auto 0; /* center vert. */
max-height: 320px;
display: flex;
flex-wrap: wrap;
}
div.test-700 {
width: 700px;
height: 320px;
background: green;
color: #ffffff;
font-size: 40px;
}
div.test-100 {
margin: auto 0; /* center vert. */
width: 100px;
height: 100px;
background: red;
outline: 1px solid black;
margin: 2px;
}
#media (max-width: 816px) {
div.container {
flex-wrap: wrap;
}
}
<div class="container">
<div class="left-fixed">
<div class="test-700">Working Flex</div>
</div>
<div class="right-variable">
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
<div class="test-100"></div>
</div>
</div>
Related
I'm just trying the FlexLayout for different screen sizes.
The 3 boxes/divs below should be side to side on a large display, if it shrinks they should be above each other. But my top div is outside of my window and I don't want that.. How can I fix that?
<div class="container" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="space-around center">
<div class="asd" [style.background-color]="'black'"></div>
<div class="asd" [style.background-color]="'green'"></div>
<div class="asd" [style.background-color]="'blue'"></div>
</div>
.asd {
min-height: 500px;
min-width: 400px;
}
.container {
height: 100%;
}
Flex elements won't stack unless you use flex-wrap: wrap along with a min-width or flex-basis declaration.
Basically, if the number of flex elements in the row would need to be smaller than their min-width they'll wrap to the next line.
.flexContainer {
display:flex;
max-width: 80%;
margin: 20px;
justify-content: space-between;
flex-wrap: wrap;
}
.flexItem {
background: #dddddd;
padding: 20px;
min-width: 200px;
margin: 0 10px 10px 0;
}
<div class="flexContainer">
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
<div class="flexItem">Flex</div>
</div>
I am looking at having a header to a horizontal scrollable section that would have a date counter along the top, spanning the length of a year. Each date is represented by a single div. Weekends have a background color that is different than the week days. I am not using any graphics library, just straight HTML, CSS and JS. It is preferable that I do not need to change this.
My goal is to make it so that the weekend background color will extend down the main body of the panel without disrupting the layout and elements present there. The end result would look something like this:
Things I thought could potentially work:
Extend the background color of the weekend cells so that they continue vertically down the height of the main panel. This requires that background colors of cells can extend beyond the bounds of an element
Have the panel show different background colors at certain intervals. This would require the ability to alternate the background color of the SAME div multiple times
I am definitely open to any other ideas if I am simply unware of a better way to do things.
Optimization is a key concern, as I am expecting to have a couple of hundred rows of data (in a vertically scrollable div) as well as 300+ columns (in a horizontally scrollable div). I have run a test to determine if it was still responsive enough with a div per cell. The answer was most definitely not: it took seconds to load, it was laggy with the scrolling and overall just not nice to use. Not particularly surprising at 60,000 elements.
I have tried doing the following:
Doing a transform and pseduo selector on the weekend elements to extend the background (have had trouble with the :after element also extending the size of the current element). I've also had a problem trying to get the :after selector to apply down rather than to the right, even after trying some basic transforms
Making the entire thing discrete and adding divs for every representable day of a row. This was awful and unfortunately unusable at the scale I am expecting, but technically has the desired appearance
Sample code that can used to get a similar situation to my current environment:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
Any help with concepts that could assist with this would be much appreciated, and any references to reading materials would be icing on the cake. Thanks a tonne in advance.
You can manipulate the .weekend::after pseudo element by adding this code:
.weekend::after{
content:'';
position:absolute;
height:100%;
width:25px;
top:1em;
z-index:-1;
background-color: #efefef;
}
Here is the full working code:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
.weekend::after{
content:'';
position:absolute;
height:100%;
width:25px;
top:1em;
z-index:-1;
background-color: #efefef;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
You can add an :after and set a width of 0 with a margin-left equal to the width of the cell (16px in this case.
This can be seen i the following:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
.weekend:after {
background-color: #efefef;
width: 20px;
height: 100vh; /* Adjust to suit */;
content: "";
display: inline-block;
margin-left: -16px;
z-index: -1;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
I am trying to create tab module such as this:
https://codepen.io/oknoblich/pen/tfjFl
However I am having difficulty since I can not change the HTML layout:
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
The problems are that absolute positioning removes the content from the document flow, while other methods prevents the content from being the full width of the page.
I created two codepen's that illustrates the difficulties:
https://codepen.io/dwigt/pen/pOQpLd (absolute positioning removes content from document flow)
https://codepen.io/dwigt/pen/YOREOJ (flexbox layout does not take up full page-width)
Is there anyway I can replicate the tab functionality using this HTML layout and no javascript?
You can use display: contents (which is unfortunately not too well supported) combined with flexbox layout with wrap, set on the .wrapper element. This way, tab-headers and tab-contents will be treated equally, as if they were at the same level with one another - the .container elements are "transparent" to the layout engine. As a result, they will all be laid out with flexbox logic applied. Finally, to have the three tab headers display first, we set the order of the tab contents to some high value (here 100), and since we have flex wrap enabled, the content is then pushed downwards to a new line, below the headers. See example below:
.wrapper {
max-width: 300px;
display: flex;
flex-wrap: wrap;
height: 100%;
}
.container {
height: 50px;
display: contents;
}
.container .tab-header {
width: 100px;
max-width: 100%;
max-height: 100%;
flex: 1 0 33.33%;
}
.container .tab-content {
display: none;
height: 200px;
order: 100;
}
.container.current .tab-content {
display: block;
width: 300px;
left: 0;
}
.footer {
height: 500px;
width: 300px;
display: block;
}
.red {
background: red;
}
.teal {
background: teal;
}
<div class="wrapper">
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
<div class="container">
<div class="tab-header">Tab3</div>
<div class="tab-content teal">Content3</div>
</div>
</div>
<div class="footer red">Footer Text</div>
This isn't quite perfect because the first tab is a bit wider, but give this a shot and see if this doesn't get your closer to your goal. It allows your tabs to be 100% and also allows you to add more tabs that space evenly from edge to edge of your container.
Let me know how it works out :D
Add display: table-cell and width: 100% to your css selector label
label {
display: table-cell;
width: 100%;
margin: 0 0 -1px;
padding: 15px 25px;
font-weight: 600;
text-align: center;
color: #bbb;
border: 1px solid transparent;
}
I have two instances of the same row-component that has display: flex and justify-content: space-between:
<div class="component-row">
<div>looooooooooong</div>
<div>short</div>
<div>mediummm</div>
</div>
<div class="component-row">
<div>looooooooooong</div>
<div>short</div>
<div>mediummm</div>
</div>
The spacing between the children of each component will be different because the children have different widths. Without changing the order of the children, how can I make sure that both component instances have the same amount of space between each of their children? Within the instance, the space (ex. the space between long and short) doesn't have to be equal - what I want is the space between the 1st and 2nd child of both instances to be the same, and the space between the 2nd and 3rd child of both instances to be the same.
It sounds really easy solution but it is, just give a fixed width on a class and then place it on the .component-row childrens.
.component-row {
display: flex;
justify-content: space-between;
}
.eq1 {
width: 30%;
}
.eq2 {
width: 20%;
}
.eq3 {
width: 35%;
}
<div class="component-row">
<div class="eq1" style="background-color: red;">looooooooooong</div>
<div class="eq2" style="background-color: purple;">short</div>
<div class="eq3" style="background-color: pink;">awdasdsdasad</div>
</div>
<div class="component-row">
<div class="eq1" style="background-color: green;">looooooooooong</div>
<div class="eq2" style="background-color: yellow;">srt</div>
<div class="eq3" style="background-color: blue;">mediummm</div>
</div>
The most obvious would be to give each item a width, though if you can't or don't want, flexbox is not the best solution, a grid is.
As CSS Grid lacks good browser support, CSS Table doesn't, and is the perfect choice to accomplish this task.
.component-container {
display: table;
width: calc(100% - 40px);
}
.component-row {
display: table-row;
}
.component-row div {
position: relative;
display: table-cell;
border: 1px solid gray;
}
.component-row div:nth-child(2) {
left: 20px;
}
.component-row div:nth-child(3) {
left: 40px;
}
<div class="component-container">
<div class="component-row">
<div>looooooooooong</div>
<div>mediummm</div>
<div>short</div>
</div>
<div class="component-row">
<div>short</div>
<div>looooooooooong</div>
<div>mediummm</div>
</div>
</div>
I have a container with fixed width. Also, it holds fixed-width, fixed-height items inside. I want the items inside the container to have a space between them, but I also want them to touch the border of the container. This way, I can't just add a margin to every item, since that would cause them not to touch the border of the container. See the snippet:
.container {
width: 400px;
border: 4px solid red;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: center;
align-content: space-between;
background-color: #AAAAFF;
}
.item {
flex: 0 0 60px;
height: 100px;
width: 60px;
height: 60px;
border: 2px solid blue;
background-color: gray;
box-sizing: border-box;
}
<div class="container">
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
<div class="item">foo</div>
</div>
The result is almost what I wanted, but I want to,
Add a 10px space between pairs of rows;
Make the last row align to the left - I don't want that huge spacing between the last items.
How is that possible?
This should add the desired space between the rows.
.item:nth-child(n + 7)
{
margin-top: 10px;
}
It is called structural-pseudo-classes, read all about it here:
http://www.sitepoint.com/getting-to-know-css3-selectors-structural-pseudo-classes/
I don't know if this can be done with css flex, however with all of your heights and width set the flex is rather unnecessary, using inline-block can do this easily.
.container {
width: 400px;
border: 4px solid red;
display: inline-block;
background-color: #AAAAFF;
}
.item {
display: inline-block;
min-width: 60px;
height: 60px;
border: 2px solid blue;
background-color: gray;
box-sizing: border-box;
}
.item:nth-child(n+7){
margin-top: 10px;
}
note: I added the margin fix from Örvar's answer just to make the answer complete, so credit for that goes to him. Do note that if you change the width of either your items of container the n+7 might need to be adjusted, so this is not entirely dynamic, but I can see no other way to do that.