I want to be able to swap the position of two divs depending on the screen size.
I have this JSfiddle.
HTML
<div class="divMain">
<div class="div2">
</div>
<div class="div3">
</div>
</div>
CSS
.divMain{
height: 500px;
width: 500px;
border: 2px solid black;
}
.div2{
display: inline-block;
height: 200px;
width: 200px;
border: 2px solid red;
}
.div3{
display: inline-block;
height: 200px;
width: 200px;
border: 2px solid blue;
}
#media only screen and (max-width: 500px) {
.div2{
background-color: red;
}
.div3{
background-color: blue;
}
}
}
When the screen size is wider than 500px wide, i want div2 to be on the left and div3 to be on the right. Once the screen size reduces to 500px or smaller, i'd like div2 to be on the right and div3 to be on the left.
How would i go about this?
Help is much appreciated.
Thanks
You can add a float left on your div 3
#media only screen and (max-width: 500px) {
.div2{
background-color: red;
}
.div3{
background-color: blue;
float:left;
}
}
This pulls div 3 to the left of div 2
fiddle: https://jsfiddle.net/x0x2tu38/3/
It may be something of a hack, but a technique I find myself reaching for when I want an element to be be laid out in a different part of my HTML document depending on screen size – as opposed to just styled differently – is to just duplicate the element and then hide or show the two versions of the element using #media queries.
Using your example:
HTML
<div class="divMain">
<div class="div2 visible-small"></div>
<div class="div3"></div>
<div class="div2 visible-large"></div>
</div>
CSS
.divMain{
height: 500px;
width: 500px;
border: 2px solid black;
}
.div2{
display: inline-block;
height: 200px;
width: 200px;
border: 2px solid red;
}
.div3{
display: inline-block;
height: 200px;
width: 200px;
border: 2px solid blue;
}
#media only screen and (max-width: 500px) {
.visible-large {
display: none;
}
.div2{
background-color: red;
}
.div3{
background-color: blue;
}
}
#media only screen and (min-width: 501px) {
.visible-small {
display: none;
}
}
I can't speak to whether or not this has performance implications, but it certainly gets the job done. I prefer it mostly because it covers all cases – not just when the elements in question are right after one another in the HTML document – but also because I find the behavior of the css float property to be beyond the grasp of my simple mind.
I should also say that, if you're using Bootstrap, then helper classes that do this are built in! And it looks like Foundation has classes that do something similar.
Try to play with flexes:
display
This defines a flex container; inline or block depending on the given value. It enables a flex context for all its direct children:
.container {
display: flex; /* or inline-flex */
}
flex-direction
This establishes the main-axis, thus defining the direction flex items are placed in the flex container. Flexbox is (aside from optional wrapping) a single-direction layout concept. Think of flex items as primarily laying out either in horizontal rows or vertical columns:
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
row (default): left to right in ltr; right to left in rtl
row-reverse: right to left in ltr; left to right in rtl
column: same as row but top to bottom
column-reverse: same as row-reverse but bottom to top
flex-wrap
By default, flex items will all try to fit onto one line. You can change that and allow the items to wrap as needed with this property. Direction also plays a role here, determining the direction new lines are stacked in.
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap (default): single-line / left to right in ltr; right to left in rtl
wrap: multi-line / left to right in ltr; right to left in rtl
wrap-reverse: multi-line / right to left in ltr; left to right in rtl
justify-content
This defines the alignment along the main axis. It helps distribute extra free space left over when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.
.container {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
flex-start (default): items are packed toward the start line
flex-end: items are packed toward to end line
center: items are centered along the line
space-between: items are evenly distributed in the line; first item is on the start line, last item on the end line
space-around: items are evenly distributed in the line with equal space around them. Note that visually the spaces aren't equal, since all the items have equal space on both sides. The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has it's own spacing that applies.
align-items
This defines the default behaviour for how flex items are laid out along the cross axis on the current line. Think of it as the justify-content version for the cross-axis (perpendicular to the main-axis).
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
flex-start: cross-start margin edge of the items is placed on the cross-start line
flex-end: cross-end margin edge of the items is placed on the cross-end line
center: items are centered in the cross-axis
baseline: items are aligned such as their baselines align
stretch (default): stretch to fill the container (still respect min-width/max-width)
align-content
This aligns a flex container's lines within when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
flex-start: lines packed to the start of the container
flex-end: lines packed to the end of the container
center: lines packed to the center of the container
space-between: lines evenly distributed; the first line is at the start of the container while the last one is at the end
space-around: lines evenly distributed with equal space around each line
stretch (default): lines stretch to take up the remaining space
Following above, try to use something like that in your code:
<div class="container">
<button>div1</button>
<button>div1</button>
</div
#media only screen and (max-width: 500px) {
.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-around;
align-items: center
}
}
I also prepared snippet for you to let you play with it.
.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: space-around;
align-items: center
}
<div class="container">
<button>div1</button>
<button>div1</button>
</div>
More info on flexes (including examples) you can find here
Related
I want to create a website, part of which has two elements in a container: title text and a button. I want to place them in the center of the main axis (the container), with some space between them. I don't like the justify-content: space-around option because it leaves too much space in the middle. So to do this, I would use left/right margins for each of the elements. But I also want to use flex-wrap: wrap;, meaning that if the screen size is too small to fit both of the elements, css would transfer the button to the next line. Every time this happens however, the margin-left still remains on the button, so it looks off-centered (see image).
Any ideas? Thanks.
EDIT: Using media queries messes things up, so my new question is this: Is there a way to make the space between two centered elements hold constant to all screen sizes without margins?
You can set the margin only for bigger screen sizes using CSS media queries
You're probably looking for justify-content: space-evenly in combination with text-align: center, align-items: center, and flex-wrap: wrap. This will separate the content out evenly, whilst simultaneously allowing it to wrap around without any margins when the viewport isn't wide enough to contain both elements.
.container {
display: flex;
align-items: center;
justify-content: space-evenly;
text-align: center;
flex-wrap: wrap;
border: 1px solid black;
height: 100px;
/*max-width: 80px;*/ /* Turn on to see the wrap */
}
.content {
flex: 1;
}
<div class="container">
<div class="content">content</div>
<div class="content">content</div>
</div>
I have a div that is set to be 50% of the page's width at all times, and is centered.
I would like to add an element to it's side so that the element touches the div's left edge (on different screen sizes). The element has a fixed max-width.
I've tried:
#element {
position: absolute;
align: left;
padding-left: 3vw;
}
It works on most common screen sizes, but as I go very small or very big the element either overlaps with the div or there is a gap. What I would like ideally would be for the element to stick to the side of the div.
Absolute positioning is very problematic for this kind of layout. I recommend a flexbox layout.
In order to achieve this layout we will need to add a couple divs. One div to act as the 3rd column, I gave it the class ghost because it will contain nothing although the demo here uses a red border so you can see it.
The other div I added wraps the special element you want to stick to the middle div. This is so the element wrapper (.element-wrap) is a flex child, not the element itself.
Next, give the container of these 3 divs display: flex, turning it into a flexbox container:
section {
display: flex;
align-items: center; /* vertical alignment */
justify-content: center; /* horizontal alignment */
}
The align-items property allows you to vertically align the items inside, while justify-content allows you to align them horizontally.
The center div, which I gave a blue background, will of course be in the middle of the layout and maintains its width with width: 50vw;. The 2 divs on the side have a class applied .flex-child which get this CSS:
.flex-child {
flex-grow: 1;
flex-basis: calc((100% - 50vw) / 2);
}
flex-grow: 1 allows those side divs to expand with the size of the screen. The flex-basis rule determines the starting size, where I am using a calc() function to dynamically calculate the width.
Now, the special element with the yellow background needs to be positioned next to the blue background, which is achieved here by turning its wrapper div into a flexbox too and aligning the content to the right:
.element-wrap {
display: flex;
justify-content: flex-end;
}
* { box-sizing: border-box; }
section {
display: flex;
align-items: center;
justify-content: center;
/* just for demo */
background: #eee;
}
.flex-child {
flex-grow: 1;
flex-basis: calc((100% - 50vw) / 2);
/* just for demo */
border: 1px solid red;
}
.half-screen {
width: 50vw;
min-height: 300px;
background: dodgerblue;
}
.element-wrap {
display: flex;
justify-content: flex-end;
}
.element {
/* just for demo */
background: yellow;
}
<section>
<div class="flex-child element-wrap">
<div class="element">
ELEMENT that we are<br>
getting to stick to the side<br>
of the 50vw div.
</div>
</div>
<div class="half-screen">
50vw DIV
</div>
<div class="flex-child ghost"><!-- nothing here --></div>
</section>
First Edit: if i use align-items: stretch; I am able to stretch my flex items, I don't know what to make of it, but I was playing around with it, and thought I should add this info as edit as well, align-items: stretch value, stretching the flex items.
Second edit : Ok may be i am not clear, i am not looking for solution, i just want to know why it's not streching with justify-content, that's it, i can solve this problem my self, by editing the code, but i want to know the reason, why it is acting the way its acting.
I already read this answer Flex item not filling screen height with "align-items: stretch"
But my problem is different, as soon as I add align-items, flex-items stop stretching, before adding this property they work fine, I know I can solve this problem by adding height to 100%, but I am not interested in that, I want to know why it's behaving this way.
Note: I am using chrome
My code please read the comment, in the code
.container {
font-size: 36px;
height: 800px;
border: 1px solid black;
display: flex;
flex-wrap: wrap;
align-items: center;
/* as soon as i add this align-items property or my items
stop streching, i don't get it, if use value stretch it streches
the my items, please read the note first edit in the question,
it is at the top */
align-content: stretch;
}
.box {
width: 400px;
color: #fff;
}
.box1 {
background: blue;
}
.box2 {
background: red
}
.box3 {
background: yellow
}
.box4 {
background: black
}
<div class="container">
<div class="box box1">Home</div>
<div class="box box2">Menu</div>
<div class="box box3">About Us</div>
<div class="box box4">Contact Us</div>
</div>
Your box items can't both stretch and center at the same time.
Combining align-items and align-content won't make that happen as align-items applies on flex items on a single row and align-content when they wrap.
Note, you don't need to add align-items/content and set their value to stretch, it is their default
As for a solution, setting the box to height: 100% will make them look stretched, though will give a completely different result compared to make use of the align-items/content's stretch value.
With a fixed height they will be that set height, no matter if there will be 2 or more rows, with stretch whey will adjust their height to fit their parent. Simply put, 2 rows will make them 50% high, 3 rows 33.33% high and so on.
Assuming it is the text in the box you want centered, along with the box to stretch, simply make the box a flex container too.
Add display: flex; align-items: center to the box and it likely will layout the way you want.
If you want the text to also center horizontally, I here added justify-content: center;, which you can either keep or remove.
.container {
font-size: 36px;
height: 800px;
border: 1px solid black;
display: flex;
flex-wrap: wrap;
}
.box {
width: 400px;
color: #fff;
display: flex;
align-items: center; /* vertically center */
justify-content: center; /* horizontally center */
}
.box1 {
background: blue;
}
.box2 {
background: red
}
.box3 {
background: yellow
}
.box4 {
background: black
}
<div class="container">
<div class="box box1">Home</div>
<div class="box box2">Menu</div>
<div class="box box3">About Us</div>
<div class="box box4">Contact Us</div>
</div>
add flex-grow to the columns, they will auto stretch.
Dont include a height or a width.
You need to use stretch value for align-items property if you want to stretch the items, not center value. So if you just change align-items:center; to align-items:stretch; it will solve your problem.
https://codepen.io/julysfx/pen/weVvpp
I'm not sure if you are trying to align the boxes to the center and stretch? You should try adding justify-content:center to the .container:
justify-content: center;
Working pen with markup and css you added: https://codepen.io/anon/pen/dRxyVG
align-items will align your boxes up along the cross axis, whereas justify-content will align them along the main axis.
align-content is more like adjusting the rows or columns in relation to the flex container. The vertical direction if flex-direction is row, and horizontal if flex-direction is column. Using align-items is adjusting the row's items on the main axis, you might be able to see how they interact a little better if you make the content random sizes: https://codepen.io/anon/pen/weVBBE
When you're setting align-items:center; you're telling the items to align to the center, and they aren't going to stretch.
If you're trying to get the text in the middle of the boxes and have them stretch, you need to apply that to the children ie .box of the .container:
https://codepen.io/anon/pen/LLwEGW
Remove height and width from your code. If you want to use the stretch value in the align-items property of display flex you must need to assure that you had not given pre-defined value. In that case it will neglect the values given in align items and run the code.
I was wondering how to justify how much space is allowed in justify-content: space-between for flexbox.
Currently, my items are spaced but they have way too much space between them I want just a little space between them so they can settle somewhere in the middle in a row.
The snippet below will hopefully clarify what I'm struggling with.
Let me know if you need me to clarify further. Thanks!
#qwrapper {
display: flex;
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
}
.row {
flex: 0 auto;
height: 100px;
margin: 0;
}
#lighticon {
padding-bottom: 30px;
}
#media (max-width: 800px) {
#qwrapper {
flex-direction: column;
align-items: center;
}
}
#media screen and (max-width: 480px) {
#qwrapper {
flex-wrap: wrap;
}
.row {}
}
#media only screen and (min-width: 760px) {
#qwrapper {
justify-content: space-between;
margin: 10px;
}
#lighticon {
position: relative;
margin-left: 100px;
}
}
<div id="qwrapper">
<h3 id="michelle" class="row">"She always thinks of her clients."
<br>
</h3>
<img src="https://cdn4.iconfinder.com/data/icons/black-icon-social-media/512/099310-feedburner-logo.png" class="row" alt="" id="lighticon" />
<h3 id="jerry" class="row">"Very smart, creative person, problem solver."
<br>
</h3>
</div>
The justify-content property uses the available space on the line to position flex items.
With justify-content: space-between, all available space is placed between the first and last items, pushing both items to opposite edges of the container.
You wrote:
I was wondering how to justify how much space is allowed in justify-content: space-between for flexbox.
With space-between in row-direction, you would have to control the width of the flex container. So if you want there to be less space between flex items, then you would need to shorten the width of the container.
Or you could use justify-content: space-around.
However, these solutions are suboptimal.
The right way to go about this would be to use margins.
You wrote:
Currently, my items are spaced but they have way too much space between them I want just a little space between them so they can settle somewhere in the middle in a row.
Use justify-content: center then use margins to space them apart.
My solution was :
put dummy empty divs in between with a max-height specified
change space-between to flex-start
set the content blocks to nogrow
set the dummy divs to grow
Then the spaces grow up to a max specified.
The approach with using margins is not a universal solution if you want space-between, because it would set a margin on all the flex-elements, also on the first and last elements on a line or column. Using :first-child / :last-child/ :nth-child() selector doesn't help when flex-wrap: wrap is set, because you can never tell which elements will be first and last on a wrapped line or column.
A selector like :wrapped would be helpful, but sadly it doesn't exist.
So my conclusion is that when you really want to unleash the flexibility and responsiveness of the flexbox, you can't control the margins… Missed opportunity of the spec I'd say.
I find myself adding right margin to all the boxes (in this case three)
.three {
margin-right: 2%
}
and then getting rid of it so the last box aligns right
.three:nth-child(3) {
margin-right: 0%;
}
but every time I do this I think "there has to be a better way, something baked into flex-box...this works but it seems like a workaround?
The red borders are around flex items. They have
flex-grow: 1
These items are contained in a flex container:
width: 100%
display: flex
flex-direction: row
align-items: flex-end
As you can see the vertical alignment is working fine.
When I put the images in, the width of the images pushes the flex items to be bigger or smaller than they should be. The width of the images overrides the width of the flex items. What I want to say is something like:
Firstly make the flex items all the same size and then size the contained images (whatever their natural size) to be the size of their container (the flex item). I've tried width: 100% and width: auto on the images. Didn't help.
This image shows the equally spaced flex items (red borders). I want the images to fit into these boxes without causing the width of the box to change. This is the behaviour I get if I replace the flex items with table cells.
This Fiddle shows the 3 equal boxes: https://jsfiddle.net/justinwyllie/zdrd89gu/
.flex-container {
display: flex;
flex-direction: row;
align-items: flex-end;
}
.flex-boxes {
flex-grow: 1;
border: 2px solid red;
}
<div class="flex-container">
<div class="flex-boxes">A</div>
<div class="flex-boxes">B</div>
<div class="flex-boxes">C</div>
</div>
This one shows an image in the middle flex item. It has completely messed up the equal boxes. The question is what do I need to do to make the cat fit into the middle box? (Fit width-wise that is; i don't mind about height).
https://jsfiddle.net/justinwyllie/zdrd89gu/1/
.flex-container {
display: flex;
flex-direction: row;
align-items: flex-end;
}
.flex-boxes {
flex-grow: 1;
border: 2px solid red;
}
.cat {
width: auto;
}
<div class="flex-container">
<div class="flex-boxes">A</div>
<div class="flex-boxes">
<img class="cat" src="http://www.publicdomainpictures.net/pictures/30000/velka/annoyed-cat.jpg" />
</div>
<div class="flex-boxes">C</div>
</div>
The flex-grow property tells flex items how much available space in the container to consume.
In your second image, the empty items are all equal width because flex-grow: 1 tells them to distribute available space equally among themselves.
Any content you put in these items will impact flex-grow since, as mentioned, flex-grow is based on the free space in the container – and content consumes space.
If you want the items to maintain a fixed width, use flex-basis.
So instead of:
flex-grow: 1;
Try:
flex: 0 0 20%; /* don't grow, don't shrink, fixed width at 20% */
The 20% is just an example, if you wanted five items per row.
Here's your revised code:
jsFiddle
.flex-container {
display: flex;
flex-direction: row;
align-items: flex-end;
}
.flex-boxes {
/* flex-grow: 1; <-- REMOVE */
flex: 0 0 33.33%; /* NEW */
border: 2px solid red;
/* box-sizing: border-box; you may need to add this property if
you enable wrapping */
}
.cat {
width: auto;
/* vertical-align: bottom; add this property if you want to remove
the small gap of whitespace underneath images
https://stackoverflow.com/a/31445364/3597276 */
}
<div class="flex-container">
<div class="flex-boxes">A</div>
<div class="flex-boxes">
<img class="cat" src="http://www.publicdomainpictures.net/pictures/30000/velka/annoyed-cat.jpg" />
</div>
<div class="flex-boxes">C</div>
</div>
Learn more here:
flex-grow not sizing flex items as expected