I need to display a questionnaire with multiple sets of options. When there are only two options, they should be displayed in two columns that have 50% width each. When there are more than two, they should be displayed in three columns that have 33.3333% with each. Currently I'm having a difficulty making the columns to 50% width when there are only two of them.
https://codepen.io/sleepydada/pen/Evjgwr
HTML:
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
<div class="answer">third answer</div>
<div class="answer">four answer</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
#media (min-width: 480px) {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
&:first-of-type {
background: #ccc;
}
.answer {
width: 100%;
background: crimson;
margin: 20px 0;
border: 1px solid blue;
#media (min-width: 480px) {
flex: 0 0 33.3333%;
}
}
}
Assuming they should wrap when more than 3 items, here is a pretty cool trick using the nth-child selector and target the items based on how many there are.
Their width is set to a default of 33.333% and then when there is only 2 items, the .answers .answer:first-child:nth-last-child(2) kicks in and make them 50%
* {
box-sizing: border-box;
}
.answers {
border: 2px solid black;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.answers:first-of-type {
background: #ccc;
}
.answers .answer {
background: crimson;
margin: 20px 0;
border: 1px solid blue;
flex-basis: 33.333%; /* default width is 33% */
}
.answers .answer:first-child:nth-last-child(2),
.answers .answer:first-child:nth-last-child(2) ~ .answer { /* 2 items */
flex-basis: 50%;
}
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
</div>
<div class="answers">
<div class="answer">first answer</div>
<div class="answer">second answer</div>
<div class="answer">third answer</div>
<div class="answer">four answer</div>
</div>
Related
I'm trying to do a responsive layout, I'm not good with css so I need help.
Here is the code:
.container {
outline: 1px solid black;
max-width: 490px;
margin: 0 auto;
}
.columns {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.map {
background-color: cyan;
width: 150px;
min-width: 150px;
height: 150px;
min-height: 150px;
margin-right: 20px;
}
.content {
outline: 1px solid black;
background-color: lightgray;
max-width: 320px;
}
.cards {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.card {
background-color: pink;
outline: 1px solid black;
width: 150px;
height: 70px;
display: inline-block;
}
.card.left {
margin-right: 20px;
}
.texts {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.text {
background-color: gold;
outline: 1px solid black;
width: 150px;
height: 200px;
display: inline-block;
}
.text.left {
margin-right: 20px;
}
<div class="container">
<div class="columns">
<div class="map"></div>
<div class="content">
<div class="cards">
<div class="card left">card #1</div>
<div class="card">card #2</div>
<div class="card left">card #3</div>
<div class="card">card #4</div>
</div>
<div class="texts">
<div class="text left">text #1</div>
<div class="text">text #2</div>
</div>
</div>
</div>
</div>
Basically there are two rows.
The first one contains an element with fixed width and height, and on the right four cards.
The second rows contains only two elements.
Each element of this layout has width 150px.
The code shown above works partially.
The first row is ok, the second one no because the gold elements should stay aligned with the cards so when cards are on the right of el1, contents should below the cards.
It is like if there were to be a hidden element (on the left side of contents) that has the same size as el1.
Also I would like everything to always be centered because now it is only if the window width is > 490px.
This is what I'd like to have:
How can I do that?
For a section on a page, I am trying to display two rectangular divs stacked up between two square divs on either side as big as the height of the two stacked divs, inside these divs are img tags.
I am using this markup because on mobile I want to be able to have them on an un-wrapped flex row with an overflow: hidden parent so I can use a swipe code to translate the X-axis. I am having problems creating this layout for desktop with this markup using the flexbox (No grid, need to support IE11). Has anyone done this layout with this markup? Thanks.
<div class="flex_container">
<div class='flex_child square'>
<img...>
</div>
<div class='flex-child rect'>
<img...>
</div>
<div class='flex-child rect'>
<img...>
</div>
<div class='flex-child square'>
<img...>
</div>
</div>
Assuming that this will be the main layout of your page you can try to set a fixed height and use column direction with flexbox:
.flex_container {
height: 100vh; /*adjust this value like you want*/
display: flex;
flex-direction: column;
flex-wrap:wrap;
}
.flex_child {
background:purple;
border:2px solid #fff;
box-sizing:border-box;
width:calc(100% / 3);
}
.square {
flex:1 1 100%;
}
.rect {
flex:1 1 47%;
}
body {
margin: 0;
}
<div class="flex_container">
<div class='flex_child square'></div>
<div class='flex_child rect '></div>
<div class='flex_child rect '></div>
<div class='flex_child square'></div>
</div>
And in case you want a better browser support you can use float/inline-block by slightly adjust the classes making the 2 squares at the start:
.flex_container {
height: 100vh; /*adjust this value like you want*/
}
.flex_child {
background:purple;
border:2px solid #fff;
box-sizing:border-box;
width:calc(100% / 3);
height:100%;
}
.square:nth-child(1) {
float:left;
}
.square:nth-child(2) {
float:right;
}
.rect {
display:inline-block;
height:50%;
vertical-align:top;
}
body {
margin: 0;
}
<div class="flex_container">
<div class='flex_child square'></div>
<div class='flex_child square'></div>
<div class='flex_child rect '></div>
<div class='flex_child rect '></div>
</div>
In case you cannot also change the classes, use some negative margin to rectify the position of the last element:
.flex_container {
height: 100vh; /*adjust this value like you want*/
}
.flex_child {
background:purple;
border:2px solid #fff;
box-sizing:border-box;
width:calc(100% / 3);
height:100%;
}
.square:first-child {
float:left;
}
.square:last-child {
float:right;
margin-top:-50vh;
}
.rect {
display:inline-block;
height:50%;
vertical-align:top;
}
body {
margin: 0;
}
<div class="flex_container">
<div class='flex_child square'></div>
<div class='flex_child rect '></div>
<div class='flex_child rect '></div>
<div class='flex_child square'></div>
</div>
Making some major assumptions about your content, but you can use absolute positioning to align things. Essentially you can pull the middle two elements out of the document flow and mimic stacking through positioning.
In this case, when above 767px, the entire row is within the document flow. When below 767px, we re-position the inner two elements and set the container to justify-content: space-between to provide the visual space.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.flex_container {
position: relative;
display: flex;
}
.flex_item {
flex: 1;
height: 120px;
border: 1px solid orange;
padding: 40px;
background-color: red;
text-align: center;
}
#media (max-width: 767px) {
.flex_container {
justify-content: space-between;
}
.flex_item {
padding: 20px;
}
.square {
flex: 0 1 33%;
}
.rect {
position: absolute;
left: calc(100% / 3);
width: calc(100% / 3);
height: 50%;
}
.rect.three {
top: 50%;
}
}
<div class="flex_container">
<div class="one flex_item square">
One
</div>
<div class="two flex_item rect">
Two
</div>
<div class="three flex_item rect">
Three
</div>
<div class="four flex_item square">
Four
</div>
</div>
Again, be careful - this assumes you can control the height of the container and the dimensions of the content within. If not, this type of layout falls apart fairly easily. As stated in the other comments, if you want more structure and stability, it'd be better to wrap the inner elements with another flex element with flex-direction: column. Just know the risks!
Try
.flex_container{
display:flex;
flex-direction: row;
border: 1px solid red;
}
.flex_container2{
display:flex;
flex-direction:column;
border: 1px solid green;
}
.flex-child{
border: 1px solid blue;
}
<div class="flex_container">
<div class='flex_child square'>A</div>
<div class="flex_container2">
<div class='flex-child rect'>B</div>
<div class='flex-child rect'>C</div>
</div>
<div class='flex-child square'>D</div>
</div>
I think you need a second flex-container.
If you add a second container to control the two rect it gets easier.
You can control the height and width of square to make them square, instead of dynamic width.
.flex-container {
display: flex;
height: 150px;
}
.container>*, .square {
background-color: purple;
}
.flex-child {
flex:1;
display: inline-flex;
margin: 2px
}
.square { flex-basis: 25%; }
.container {
flex-direction: row;
flex-basis: 50%
}
.container > * {
flex-basis: 50%;
}
.container div:first-child {
margin-right: 4px
}
#media (max-width: 767px) {
.container {
flex-direction: column;
flex-basis: 33.333%
}
.container div:first-child{
margin: 0 0 4px 0
}
}
<div class="flex-container">
<div class='flex-child square'></div>
<div class='flex-child container'>
<div class='rect'></div>
<div class='rect'></div>
</div>
<div class='flex-child square'></div>
</div>
Or: (click in full page to see changing)
.flex-container {
display: flex;
height: 150px;
}
.container>*, .square {
background-color: purple;
}
.flex-child {
flex:1;
display: inline-flex;
margin: 2px
}
.square { flex-basis: 25%; }
.container {
flex-direction: column;
flex-basis: 33.333%
}
.container > * {
flex-basis: 50%;
}
.container div:first-child {
margin: 0 0 4px 0
}
#media (max-width: 767px) {
.square, .container>* {
height: 100px;
}
.flex-container {
height: auto;
flex-direction: column;
}
.rect {
flex-direction: column;
flex-basis: 50%
}
}
<div class="flex-container">
<div class='flex-child square'></div>
<div class='flex-child container'>
<div class='rect'></div>
<div class='rect'></div>
</div>
<div class='flex-child square'></div>
</div>
I have a page that is 50/50 wide. The left half has a row with six divs.
Criteria:
6 squares must always remain square.
First 5 squares should have margin/padding to right for separation.
All six squares must stay on same single row. If I can get that to work i can make the needed adjustments for responsiveness in smaller viewports.
Cross browser compatible for newest version of ie, chrome, and firefox.
My codepen: https://codepen.io/johnsontroye/pen/zzNVBr
Image:
<body>
<div class="container">
<div class="column" style="margin-right: 20px">
<div class="flex-container">
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L1
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L2
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L3
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L4
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L5
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L6
</div>
</div>
</div>
</div>
</div>
<div class="column" style="margin-left: 20px; border: 1px black solid; height: 500px">
Other stuff
<div>
</body>
.container {
display: flex;
flex-direction: row;
padding: 25px;
border: 2px red solid;
}
.column {
width: 100%;
height: 100%;
float: left;
}
.flex-container {
padding: 0;
font-size: 0;
border: 1px solid black;
box-sizing: border-box;
}
.flex-item {
position: relative;
display: inline-block;
height: 0;
width: 100%;
padding-top: 100%;
border: 1px black solid;
font-size: 20px;
color: black;
font-weight: bold;
text-align: center;
box-sizing: border-box;
}
#media (min-width: 480px) {
.flex-item {
width: 33.3333%;
padding-top: 33.3333%;
}
}
#media (min-width: 768px) {
.flex-item {
width: 16.6666%;
padding-top: 16.6666%;
}
}
.flex-item-inner {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin-right: 25px;
background: white;
border: 1px solid red;
box-sizing: border-box;
}
.flex-item-inner-content {
border: 1px solid orange;
}
.flex-item:last-child .flex-item-inner {
margin-right: 0;
color: green;
}
The main trick here is to make the div a square.
Normally one set a width, the height to 0 and a padding that equals to the width
.square {
height: 0;
width: 33%;
padding-bottom: 33%;
background: lightgray;
}
<div class="square">
<div>
Content
</div>
</div>
Now, when we add display: flex, we can't use padding with percent (Firefox bug) and we can't use height with percent since we used height: 0.
To overcome these issues when can use viewport units vw instead, and with that we can also use height instead of padding to keep it squared.
So instead of setting a width like this, calc((100% / 6) - 10px);, to spread 6 items equally with a gutter about 10px wide, we use viewport units like this calc(( (50vw - 65px) / 6) - 10px);
The 50vw is half the browser width, the 65px is the sum of the container's left/right padding, 50px, plus the 15px gutter between the columns.
This also allows us to skip the extra flex-item-inner element, skip using position: absolute on the content element, and, as we didn't use percent for the height on the flex-item, we can do like this to center the content
.flex-item-content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
And the end result is this
Fiddle demo
Stack snippet
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 25px;
border: 2px red solid;
}
.column {
flex-basis: calc(50% - 15px);
}
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.flex-item {
position: relative;
flex-basis: calc(( (50vw - 65px) / 6) - 10px);
height: calc(( (50vw - 65px) / 6) - 10px);
background: white;
border: 1px solid red;
overflow: hidden;
}
.flex-item-content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.flex-item:last-child .flex-item-content {
color: green;
}
.column .other {
padding: 15px;
border: 1px solid black;
padding-bottom: 35px;
}
.column.left .other {
margin-top: 10px;
}
.column.right .other:nth-child(n+2) {
margin-top: 10px;
}
#media (max-width: 768px) {
.flex-item {
flex-basis: calc(( (50vw - 65px) / 3) - 10px);
height: calc(( (50vw - 65px) / 3) - 10px);
}
.flex-item:nth-child(n+4) {
margin-top: 12px;
}
}
#media (max-width: 480px) {
.flex-item {
flex-basis: calc(( (50vw - 65px) / 2) - 10px);
height: calc(( (50vw - 65px) / 2) - 10px);
}
.flex-item:nth-child(n+3) {
margin-top: 15px;
}
}
<div class="container">
<div class="column left">
<div class="flex-container">
<div class="flex-item">
<div class="flex-item-content">
L1
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L2
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L3
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L4
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L5<br>L5
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L6
</div>
</div>
</div>
<div class="other">
Other stuff - left
</div>
</div>
<div class="column right">
<div class="other">
Other stuff - right
</div>
<div class="other">
Other stuff - right
</div>
</div>
</div>
This is doable with some fairly simple code, as long as the parent column's width is consistent at 50%-ish, and that the space between squares don't have to be strictly equal to a certain value. The vw (viewport width percentage) unit allows for a consistent size to be applied to both width and height of an element.
Here is an example that I boiled down to the fewest elements, and some notes help to move it in to your codebase.
Experiment with .flex-item's height and flex-basis (third value of flex) to get a size you like.
No padding or margin values are needed because justify-content: space-between; helpfully calculates that for us.
Using a line-height equal to the height of .flex-item would allow for an inner element with display: inline-block; and vertical-align: middle; to be centred.
.column {
width: 48vw;
height: 48vw;
padding: 1vw;
border: 1px solid #ccc;
}
.flex-container {
display: flex;
flex-flow: row;
justify-content: space-between;
}
.flex-item {
height: 6vw;
line-height: 6vw;
text-align: center;
border: 1px solid #ccc;
flex: 0 0 6vw;
}
<div class="column">
<div class="flex-container">
<div class="flex-item">
L1
</div>
<div class="flex-item">
L2
</div>
<div class="flex-item">
L3
</div>
<div class="flex-item">
L4
</div>
<div class="flex-item">
L5
</div>
<div class="flex-item">
L6
</div>
</div>
</div>
Only in the latest browsers? CSS Grid to the rescue! It's got great support in the latest versions. You may need some vendor prefixes still; check on CanIUse for the details.
Here it is as a fork: https://codepen.io/jackmakesthings/pen/MoJNNV
.container {
display: flex;
flex-direction: row;
padding: 25px;
border: 2px red solid;
}
.column {
width: 100%;
height: 100%;
float: left;
}
.grid-row {
display: grid;
grid-gap: 10px; /* set this to whatever space you need between boxes */
grid-template-columns: repeat(6, 1fr); /* grid autosizes 6 columns */
}
.row-item {
grid-column: 1 / 7; /* to span the whole row */
border: 1px solid;
padding: 10px;
}
.grid-item {
position: relative;
border: 1px solid;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
/* This is a nifty trick for getting those fixed aspect ratio boxes. */
.grid-item:before {
content: '';
float: left;
width: 0;
height: 0;
padding-bottom: 100%;
}
.grid-item:after {
display: table;
clear: both;
}
/* Responsive grid changes? Sure! */
#media (max-width: 1000px) {
/* We just have to change the grid template: */
.grid-row {
grid-template-columns: repeat(3, 1fr);
}
/* Unexpected thing I ran into - you also have to change this, or the grid stays big enough to accommodate the old 6-column-sized row-item. Makes sense, but vexed me for a minute! */
.row-item {
grid-column: 1 / 4;
}
}
<div class="container">
<div class="column" style="margin-right: 20px">
<div class="grid-row">
<div class="grid-item">L1</div>
<div class="grid-item">L2</div>
<div class="grid-item">L3</div>
<div class="grid-item">L4</div>
<div class="grid-item">L5</div>
<div class="grid-item">L6</div>
<div class="row-item">some other thing</div>
<div class="row-item">and another</div>
</div>
</div>
<div class="column" style="margin-left: 20px; border: 1px black solid; height: 500px">
Other stuff
<div>
How can I make this grid without creating 2 columns?
Something like this?
* {
box-sizing: border-box;
}
.container {
width: 100%;
}
.left {
width: 66.66%;
height: 400px;
float: left;
background-color: blue;
}
.right {
width: 33.33%;
height: 200px;
float: right;
background-color: red;
border: thin solid black;
}
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="right"></div>
</div>
Here is my flex box as you want ..
.vert_flex {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
border: 1px solid black;
}
.hor_flex {
display: flex;
flex-direction: row;
height: 100%;
width: 100%;
border: 1px solid black;
}
<div class="hor_flex">
<div style="flex : 2; height: 300px">width 66.6%</div>
<div class="vert_flex" style="flex : 1; height: 300px">
<div class="hor_flex" style="flex : 1">width 33.3%</div>
<div class="hor_flex" style="flex : 1">width 33.3%</div>
</div>
</div>
Flex makes life super easy..
.container {
display:flex;
}
.left {
flex:2;
background-color: #c1c1c1;
}
.container_right {display: flex;
flex: 1;
flex-direction:column}
.right {
flex:1;
background-color: #456456;
}
and the html..
<div class="container">
<div class="left">aaaaaaaaaaaa</div>
<div class="container_right">
<div class="right">bbbbbbbbbbbb</div>
<div class="right">cccccccccccc</div>
</div>
</div>
You just have to think of everything as a container.. everything inside that container can be flexed..
With Flex you need to avoid defining anything with px if possible. stick with units of
%
vw/vh r
rem/em
I'm struggling with the wrapping option of the css flexbox in combination with margins between the items.
What I'm trying to archieve is: Have a flexcontainer with wrapping enabled and a number of items with variable with and minimum width. Between these items I want to have a small gap (margin) but I don't want a margin between the item and the container on the left or right side.
Right now I'm using the first-child and last-child pseudo class but this approach doesn't work unfortunatly when the container wraps the content. See JsFiddle for a minimalistic demo.
HTML
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>
CSS
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid red;
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-left: 20px;
margin-right: 20px;
}
.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}
Any suggestions?
flexbox has some specific properties, so in your case this is what needs to be fixed:
instead of min-width use flex-basis
use justify-content: space-between
to apply margin on items there's a special hack (check out the
example -to fix border coherency apply a wrapper);
.container-bg {
width:100%;
border: 1px solid green;
overflow:hidden;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
/* border: 1px solid red;*/
margin: 0 -20px;
}
.item {
/*min-width: 100px;*/
flex: 1 0 100px;/*if you want to set 100px as min-width you'll have to set flex-shrink to 0*/
border: 1px solid black;
margin: 0 20px;
}
/*.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}*/
<p>resize the window for wrapping</p>
<div class="container-bg"><div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div></div>
EDIT :
set flex-shrink to 0 is don't want to go below a certain width..
If you add another wrapper around your items, you can use this dirty hack: https://jsfiddle.net/xw5uo2j1/13/
You set your main container to be 100% of the width, then your "sub" container to be 100% plus the amount of space between you're going to add. Then add the same amount of margin-right to the items.
.maincontainer {
width:100%;
border: 1px solid red;
}
.container {
display: flex;
flex-flow: row wrap;
justify-content:space-between;
align-content:space-between;
width:calc(100% + 5px);
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-right:5px;
}
<p>resize the window for wrapping</p>
<div class="maincontainer">
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>
</div>
UPDATED, with more than 5 items
Use calc and jusify-content: space-between;
* {
box-sizing: border-box;
margin: 0;
}
.container {
border: thin solid red;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 0 -10px;
}
.item {
border: thin solid black;
-webkit-flex: 1 1 calc(20% - 20px);
flex: 1 1 calc(20% - 20px);
margin: 0 10px;
padding: 20px;
position: relative;
}
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>