I have project where I need to display two div's. Both div's have the same width and this width is a set width. So their width doesn't scale with the screen size.
The problem I am facing is that when they are large enough to fit next to each other they need to be positioned with space in between. Both outer sides of the the div's need to touch the sides of the screen.
But when the window scales down so that they are to big to fit next to each other. Then they need to be positioned in the center of the screen underneath each other.
I have tried with flexbox, flex-wrap and justify content: space between. But when the window scales down they are both positioned at the left side of the screen and not in the center.
Here is how the should look when the screen is large enough:
And when the screen is so small that they don't fit next to each other:
Using CSS-Grids, this problem is done much cleanly:
Media query is set so perfectly. No margins needed. We just need to use min-width equal to the sum of widths of our two divs.
.wrap {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
background: green;
}
.wrap div {
height: 200px;
width: 200px;
background: black;
justify-self: center;
}
#media (min-width: 400px) {
/* min-width is calculated by width of two divs 2*200*/
.wrap {
grid-template-columns: 1fr 1fr;
}
.wrap div:first-child {
justify-self: start;
}
.wrap div:last-child {
justify-self: end;
}
}
<div class="wrap">
<div></div>
<div></div>
</div>
It's not very clear what you're trying to achive. Maybe you can do something like this:
<div class="wrap">
<div></div>
<div></div>
</div>
and
.wrap{
width: 100vw;
/* higher than 2 x box height */
height: 100vh;
display:flex;
justify-content:space-between;
background: green;
}
.wrap div{
height: 200px;
width: 200px;
background: black;
}
#media (max-width: 450px ){
/* 450px = 2 * box-size + min-gap-width(50) */
.wrap{
align-items:center;
flex-direction: column;
}
.wrap div{
margin: 50px;
}
}
codepen-demo
Related
I've been trying to achieve the layout below using flexbox. I originally had a left hand sidebar containing the image & navigation, and a main content area. On mobile, the sidebar used to wrap under the main content.
The problem with that is that I need the image to remain at the top on mobile, so I've been trying with three sibling divs in one wrapper div.
Is this even possible with flexbox or will I need to use css grid?
Although CSS Grid would be the best approach to achieve the lay-out you want, it is possible using CSS Flexbox.
You just have to create a wrapper div with three divs inside (when doing a mobile first approach) and with .content set to flex: 1 to stretch out the height of your viewport.
Then for desktop (in this case #media screen and (min-width: 1000px)), change the order (MDN reference of order) of .navigation and .content and give all three divs appropriate widths according to their needs. The only change to div.wrapper is that it needs flex-flow: column wrap to wrap correctly.
.wrapper {
display: flex;
flex-direction: column;
height: 100%;
min-height: 100%;
}
.box {
display: flex;
}
.content {
flex: 1;
}
#media screen and (min-width: 1000px) {
.wrapper {
flex-flow: column wrap;
}
.navigation {
order: 2;
}
.content {
order: 3;
}
.image,
.navigation {
width: 200px;
flex: 50%;
}
.content {
width: calc(100% - 200px);
flex: 0 0 100%;
}
}
/* Generic styling */
html,
body {
height: 100%;
}
body {
margin: 0;
padding: 0;
}
.image {
background: orange;
height: 60px;
}
.content {
background: lightblue;
}
.navigation {
background: lightgreen;
height: 60px;
}
<div class="wrapper">
<div class="box image">Image</div>
<div class="box content">Content</div>
<div class="box navigation">Navigation</div>
</div>
I'd like to know if there is a way to limit the dimensions of a grid (not the element to which it's applied, the grid itself). I explain :
Let's say we've got a footer, with a dark background, spanning all the width of your page.
This footer contains 2 sub-blocks, classnames .footer__1 and .footer__2, and we want them to occupy 2/3 and 1/3 of the available width, with a 2rem gutter.
Is there a way to give the grid containing the two sub-blocks a grid-max-width (yes, i made that up) of 60rem, without changing the block width (remember, it has a background which must be full width), without using a wrapper ?
So, the occupied width (.footer__1 + gap + .footer__2) should be 60rem max, centered horizontally.
<footer>
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</footer>
.footer {
display: grid;
grid-template_columns: 2fr 1fr;
grid-column-gap: 2rem;
/* grid-max-width: 60rem */
}
Thanks
You have to wrap it with an additional element and limit the width to the additional element.
footer {
background-image: linear-gradient(20deg, red, pink);
}
.container {
display: grid;
grid-template-columns: 2fr 1fr;
grid-column-gap: 2rem;
/* just for demo purpose */
max-width: 300px;
margin: 0 auto;
min-height: 150px;
background: white;
}
<footer>
<div class="container">
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</div>
</footer>
Without another container, I think it is not possible.
However, you can mimic it by making the footer width: 60rem and set the background as a pseudo-element and expand it.
footer {
position: relative;
z-index: 1;
width: 60rem;
margin: 0 auto;
}
footer:before {
content: '';
position: absolute;
top: 0;
left: 50%;
z-index: -1;
transform: translateX(-50%);
width: 9999px;
height: 100%;
background: green;
}
<footer>
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</footer>
The best approach, as I think, is to add div.footer__inner that will hold the two divs - .footer__1 and .footer__2.
I am using the recommended approach from this question https://stackoverflow.com/a/468080/2981429 and have two divs:
#left-pane {
float: "left";
width: "300px";
}
#right-pane {
margin-left: "300px";
}
the left pane takes up a fixed 300px width and the right pane always takes up 100% of the remaining space.
I want to add a "minimum width" to the right pane. When it gets below a width of around 300px I want to move it below the left pane.
When I try actually adding min_width: 300px to the right pane, it just extend invisibly past the boundaries of the page - it doesn't seem to be able to get below the floated left pane.
Codepen
You can use flexbox for your layout.
You can find a good point to start on MDN.
When you use a small device, you can use a media-query to get the divs on column.
For example:
#media (max-width: 600px) {
.container{
flex-direction:column;
}
#left,#right{
flex: 0 1 100%;/* set the width to 100% for the 2 columns */
}
}
.container{
display:flex;
}
#left {
flex:0 1 300px;
height: 300px;
background-color: blue;
}
#right {
flex:1 1 auto;
height: 300px;
background-color: darkred;
}
<div class="container">
<div id='left'></div>
<div id='right'></div>
</div>
that is not a float job. you need flex for this instance.
.container {
display: flex;
flex-flow: row nowrap;
width: 100%;
}
#left-pane {
width: 300px;
min-width: 300px;
}
#media only screen and (max-width: 300px) {
.container {
flex-flow: column;
}
}
using flex gives you a lot of new layout and responsive options, you can read more here: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.parent {
display: flex;
}
#left {
float: left;
width: 300px;
height: 300px;
background-color: blue;
}
#right {
height: 300px;
background-color: darkred;
width: calc(100% - 300px);
}
#media (max-width: 600px) {
.parent {
flex-direction: column;
}
#left,
#right {
width: 100%;
}
}
<div class="parent">
<div id='left'></div>
<div id='right'></div>
</div>
I want the two child div's to justify to the left and stack on each other 100% width at a certain browser media width of 1000px.
I have two child div's in a parent that appear correctly:
.relationFRAME {
background: #151515;
color: #FFF;
display: flex;
}
.relationLEFT {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.relationRIGHT {
float: right;
flex: 1;
}
I want the two child div's to justify to the left and stack on each other 100% width at a certain browser media width of 1000px.
Can someone help me understand the change in the CSS to do this?
With #media you can change the styling at an certain width and flex-direction: column; to stack the child elements on top of each other.
Here's an example:
.relationFRAME {
background: #151515;
display: flex;
}
.relationLEFT {
background: green;
flex: 1;
}
.relationRIGHT {
background: orange;
flex: 1;
}
#media only screen and (max-width: 1000px) {
.relationFRAME {
flex-direction: column;
}
}
<div class="relationFRAME">
<div class="relationLEFT">a</div>
<div class="relationRIGHT">b</div>
</div>
You can set a min-width to the child and allow wrapping on the parent :
.relationFRAME {
background: #151515;
display: flex;
flex-wrap:wrap;/* will stack element if width becomes too small */
}
.relationFRAME > div {
flex:1;
min-width:580px;/* whatever value you want to set as a break point */
/* demo use only */
border:1px solid ;
color:white;
margin:2px;
padding:0.25em;
}
<div class="relationFRAME">
<div class="relationLEFT"> Play me full page mode and resize window to check out my behavior </div>
<div class="relationRIGHT">b</div>
</div>
I want to use a simple layout, that consists of
An image
Some text
The text should be on the bottom and all remaining space should be used by the image. It seemed a simple task, but it has been a frustrating journey. Finally, I nailed but this solution doesn't work on mobile devices (Android and/or Chrome).
JSFiddle here
It looks like this on the desktop:
Unfortunately, the iPad renders it like this:
The text is barely visible, because the image took all the space. On Android (with Chrome 65 installed) it shows some of the text, but not all of it.
I use the following HTML code
<html>
<body>
<h1>TEST 123</h1>
<div class="wrapper img-top">
<img class="image" src="..." />
<div class="text">
<h2>Header</h2>
<p>...</p>
</div>
</div>
</body>
</html>
The relevant parts of the CSS looks like this (full code on JSFiddle):
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}
.wrapper {
display: grid;
grid-gap: 10px;
height: calc(100vh - 85px);
margin-bottom: 20px;
text-align: center;
align-items: center;
}
.wrapper.img-top {
grid-template-rows: 1fr auto;
}
.wrapper.img-top .image {
grid-row: 1;
justify-self: center;
}
.wrapper.img-top .text {
grid-row: 2;
justify-self: center;
}
.wrapper img.image {
max-height: 100%;
max-width: 100%;
}
I guess that there is a problem with the automatic image sizing, but I don't know what to do next? I want to have it responsive, but it just is not going to work.
Your problem is that you put fixed height on img-top. Your img is, let's say, 900 px, it's not the same on screen as iPad and desktop. Since you put your image to be 1 fr of height, it is getting bigger as screen is getting smaller. So you have two solutions, as far as I can tell, first is to restrict the size of your image, max-height: 300px;, or try putting overflow auto on .img-top.
Thanks #Jakub Muda for the suggestion about using flexboxes. I have finally fixed the problem by moving to a flexbox and fix the remaining issues.
After switching to a flexbox, I kept the same problem. The image was sized to 100% of the size of the parent wrapper div. I have fixed this by adding overflow: hidden to the image, so it will not overflow. This worked fine, but some images were distorted, because the aspect-ratio wasn't properly maintained. Adding object-fit: contain fixed this issue.
The complete sample can be found at JSFiddle, but for completeness I have added the CSS here as well:
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}
.wrapper {
display: flex;
flex-direction: column;
height: calc(100vh - 85px);
margin-bottom: 20px;
text-align: center;
align-items: center;
}
.wrapper .image {
justify-self: center;
flex: auto;
overflow: hidden; /* Important to make sure the image stays within bounds */
object-fit: contain; /* Important to make sure the image keeps its aspect ratio */
}
.wrapper .text {
justify-self: center;
flex-basis: none;
padding-top: 10px;
}
.wrapper img.image {
max-height: 100%;
max-width: 100%;
}