Change order of grid items on smaller screens - html

I am trying to use a media query so that once my layout gets below 800px wide, it goes into one column with the relevant description underneath the image.
But the order is incorrect and I get the images first and then the descriptions.
Where am I going wrong?
.container {
display: grid;
grid-template-columns: 2fr 1fr;
}
.one img {
height: 100%;
width: 100%;
object-fit: cover;
}
.two img {
height: 100%;
width: 100%;
object-fit: cover;
}
.three {
padding: 20px;
background: wheat;
}
.four {
padding: 20px;
background: gray;
}
#media only screen and (max-width: 900px) {
.container {
display: grid;
grid-template-columns: 1fr;
}
}
<div class="container">
<div class="one">
<img src="https://picsum.photos/id/600/600/300">
</div>
<div class="two">
<img src="https://picsum.photos/id/600/601/300">
</div>
<div class="three">
This is the description for the first image
</div>
<div class="four">
This is the description for the second image
</div>
</div>

By default the grid items will be place one below the other (as per the order the grid items appear in the markup) if you specify grid-template-columns: 1fr. You can use grid-row: 2 to the description to the first image (three) - this places it correctly.
See demo below:
.container {
display: grid;
grid-template-columns: 2fr 1fr;
}
.one img {
height: 100%;
width: 100%;
object-fit: cover;
}
.two img {
height: 100%;
width: 100%;
object-fit: cover;
}
.three {
padding: 20px;
background: wheat;
}
.four {
padding: 20px;
background: gray;
}
#media only screen and (max-width: 900px) {
.container {
display: grid;
grid-template-columns: 1fr;
}
.three {
grid-row: 2; /* added */
}
}
<div class="container">
<div class="one">
<img src="https://picsum.photos/id/600/600/300">
</div>
<div class="two">
<img src="https://picsum.photos/id/600/601/300">
</div>
<div class="three">
This is the description for the first image
</div>
<div class="four">
This is the description for the second image
</div>
</div>

From my comment and maybe not the kind of answer you look for ( I was waiting for a feed back, so i go with the idea ... too long to be just a comment).
When you run your HTML witout style, img and description do not match.
You could use figure and figcaption to describe the content and link image with its description , img and description in the same container is enough , a div + a p is fine too.
Default, will let them stack on top of each others, this is what you expect when the screen is less than 900px wide. nothing to do there .
You need to mind when it is wider.that's where your mediaquerie comes usefull.
Here is the demo of the coding idea :
/* commun style */
img {
box-sizing:border-box;
display:block;
width: 100%;
height: 100%;
object-fit: cover;
padding: 1em 1em 0 1em ;
}
figure figcaption{
display:block;
margin:0 1em;
background: wheat;
}
figure:nth-child(even) figcaption{
background:gray
}
/* reordering visual layout when window is wider than 900px */
#media only screen and (min-width: 901px) {
/* grid , what you want to use */
.container {
display:grid;
grid-template-columns:2fr 1fr;
}
/* not the best , we will try to make figure side by side looking like 2 rows .... */
figure {
display:flex;
flex-direction:column;
}
/* to fake the rows, trying to set heights each should fill */
img {
flex:10
}
/* works for about 2 1em lines, then visual breaks */
figcaption {
flex:1
}
/* use of supports in case browser is able to get rid of figure in the way for the grid sytem set on container, This your initial idea, to use the grid model for img and text and draw a grid with cell alignement */
#supports (display:contents) {
figure {
display:contents
}
img {
grid-row:1;
}
}
}
<div class="container">
<figure>
<img src="https://picsum.photos/id/600/600/300">
<figcaption>
This is the description for the first image<br>another line
</figcaption>
</figure>
<figure>
<img src="https://picsum.photos/id/600/601/300">
<figcaption>
This is the description for the second image
</figcaption>
</figure>
</div>
A different structure and the use of display:contents is surely not what you expected , i hope it brings you to learn something instead your answer. See links to usefull ressources below.
The codepen to play with : https://codepen.io/gc-nomade/pen/EJBmee
about display :
https://css-tricks.com/get-ready-for-display-contents/
The issue is that the only way for elements to participate in the same CSS grid together (or flexbox for that matter) is for them to be siblings. So, in some cases we might be incentivized to forego HTML semantics for the benefit of layout (not great).
One answer to this is display: contents;—a magical new display value that essentially makes the container disappear, making the child elements children of the element the next level up in the DOM.
about figure :
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure
The HTML <figure> (Figure With Optional Caption) element represents self-contained content, potentially with an optional caption, which is specified using the (<figcaption>) element. The figure, its caption, and its contents are referenced as a single unit.
about #supports :
https://developer.mozilla.org/en-US/docs/Web/CSS/#supports
The #supports CSS at-rule lets you specify declarations that depend on a browser's support for one or more specific CSS features. This is called a feature query. The rule may be placed at the top level of your code or nested inside any other conditional group at-rule.

The elements in one column are showing up in the order they appear in your code. You have not created any reason for them to appear in any other order.
You could re-order the HTML so they appear in your preferred order.
Or, here's one CSS method – using grid-template-areas – that may work for you:
.container {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-areas: "one two"
"three four";
}
.one { grid-area: one; }
.two { grid-area: two; }
.three { grid-area: three; }
.four { grid-area: four; }
img {
height: 100%;
width: 100%;
object-fit: cover;
}
.three {
padding: 20px;
background: wheat;
}
.four {
padding: 20px;
background: gray;
}
#media only screen and (max-width: 900px) {
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-areas: "one"
"three"
"two"
"four";
}
}
<div class="container">
<div class="one">
<img src="https://picsum.photos/id/600/600/300">
</div>
<div class="two">
<img src="https://picsum.photos/id/600/601/300">
</div>
<div class="three">
This is the description for the first image
</div>
<div class="four">
This is the description for the second image
</div>
</div>

Related

How can I shrink the height of a flex child to 50% only?

I am trying to have a UI like this :
This is how I have tried doing it :
A div at the top as cover Image
The next div containing two child divs as profile photo & UI details as -
<div>Image Cover photos<div>
<div style="display : flex;">
<div>profile photo</div>
<div>UI Details Card</div>
</div>
Then I'm using the transform : translateY(-50%) to the profile photo div to move 50 percent of the portion on top of the background cover photo.
This, however creates a problem, the UI details remains at the same place(which is ideal), but the baseline has been changed.I want it to have only 50% of the height, so the baseline matches with the profile photo as well, and also UI details wcard will have some text, I do not want it to overlap on the Cover Image background as well(as that of profile photo). How can I achieve this?
One way to solve this problem is to use CSS grid to place everything.
body {
padding: 100px;
}
.card {
height: 300px;
width: 300px;
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: repeat(3, 1fr);
outline: 1px solid;
}
.details {
background-color: blanchedalmond;
grid-area: 3/2/4/3;
}
.photo {
background-color: aquamarine;
grid-area: 2/1/4/2;
}
.cover {
grid-area: 1/1/3/3;
background-color: grey;
}
.cover img,
.photo img {
height: 100%;
width: 100%;
}
<div class="card">
<div class="cover">
<img src="https://source.unsplash.com/random/?1" alt="">
</div>
<div class="photo">
<img src="https://source.unsplash.com/random/" alt="">
</div>
<div class="details">Details here</div>
</div>
Here's a diagram showing the different grid areas :
Notice the overlap region between the blue box (photo) and the red box (cover). Since the photo div appears after the cover div in the DOM, the photo div will have higher priority and will occupy this overlap region.
You can make a 2 column, 3 row grid and place items where you want them.
Here's a simple example:
.container {
display: grid;
grid-template-columns: 1fr 4fr;
grid-template-rows: 1fr 1fr 1fr;
width: 30vw;
height: 20vw;
}
.container :nth-child(1) {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
background: red;
}
.container :nth-child(2) {
grid-column: 1;
grid-row: 2 / span 2;
background: green;
}
.container :nth-child(3) {
background: blue;
}
<div class="container">
<div></div>
<div></div>
<div></div>
</div>
Obviously you will want to alter the relative sizes of the grid to suit your particular case.
Note: it depends on whether you want to put some text in the first item so that it comes directly above the second item or not as to whether you start the first div in the first column or the second column.

How do I create 2 column divs that stack on top of each at different screen sizes?

The div container is breaking my page. It's overriding a container used elsewhere. Is there any other alternative I can use to still have the same effect i.e the div columns sit next to each but at different screen resolutions, they stack on top of each other, and both retain equal width and length as they shrink?
How do I create two responsive divs that sit next to each other and stack on top of each other at different screen sizes? The dimensions are specific (each div is 350 x 217 px).
One div will have a text centred horizontally within the div but also left aligned and the other will be an image.
Below is the ideal end result. I'm a newbie to dev and this is for an assignment that's overdue. I've been fiddling around for the past couple of days and I keep going round in circles.
Responsive view on smaller screens:
* {
box-sizing: border-box;
}
.column {
flex: 1;
}
.left {
background-color: #e0e620;
}
.center {
margin: auto;
border: 3px solid green;
padding: 50px 50px;
}
.right {
background-color: #E5E5E5;
}
.row {
display: flex;
}
img {
width: 100%;
display: block;
}
#media screen and (max-width: 600px) {
.row {
width: 100vw;
display: block;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
The image is 350 x 217. Here is the ideal look below:
The below screen is what I would like to achieve without changing the existing width and height of yellow div? How do I go about achieving that?
add display: grid to the parent element .row;
add grid-template-columns: 1fr 1fr to the parent element (.row) to have a 2-column layout.
For screens at 600px or below you change the grid-template-columns to 1fr for the element .row to get a 1-column layout. To have both elements have the same height, you can use grid-auto-rows: 1fr on the parent element.
To maintain the normal block-level-behavior you add display: flex; flex-direction: column to the .left column. Flexbox will allow you do vertical center the text.
To vertical center the text you have to align it to the main-axis (flex-direction: column) with justify-content: center
* {
box-sizing: border-box;
}
.row {
display: grid;
grid-template-columns: 1fr 1fr;
}
#media only screen
and (max-width: 600px) {
.row {
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
}
}
.left {
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: center;
}
img {
width: 100%;
display: block;
object-fit: contain;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
Your question needs work.
You want the specific div widths to be 350px x 217px, but when you get to a min-width of 600px, that width of 350px isn't going to work anymore. You will struggle to have a responsive page if you set explicit heights and widths. You need to let elements fill their spaces naturally.
That said, I've created a solution that I think would work best based on the images you've provided.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
img {
max-width: 100%;
height: auto;
}
.container {
display: flex;
flex-direction: column;
}
#media screen and (min-width: 600px) {
.container {
flex-direction: row;
min-height: 217px;
}
}
.inner {
background-color: #E0E61F;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
width: 100%;
min-height: 217px;
}
.inner span {
padding-left: 1rem;
min-height: unset;
}
.inner img {
min-height: 217px;
object-fit: cover;
}
<div class="container">
<div class="inner">
<span>The Info</span>
<span>Download Now</span>
</div>
<div class="inner">
<img src="https://placekitten.com/1600/900" alt="">
</div>
</div>
Like mentioned above i would start with mobile view. You can create a parent div around your two boxes called container with the following css properties
display:flex
flex-direction: column
Then add a media query set at the width you would like this divs to be side by side and change the flex direction on your container div to row
flex-direction: row

How can I change the layout and order of children with flexbox? [duplicate]

This question already has answers here:
Left column and stacked right column using flexbox CSS [duplicate]
(2 answers)
Closed last year.
I have been trying many different methods to achieve the following but could not.
I tried using media query to change the order of the children within the flex box of the div that contains all 3 but it seems like I can only do so when all 3 children are divs. However when all 3 children are divs, I cannot achieve the desktop outcome. Basically the header and the paragraph text will each take a column.
Any help would be greatly appreciated.
Exiting code: https://codepen.io/lionellloh/pen/BawVpjm
<div class="parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/2/27/Red_square.svg">
<h1> This is a header </h1>
<p> This is some body text that is very interesting </p>
</div>
.parent {
display: flex;
flex-wrap: wrap;
}
#media only screen and (max-width: 900px) {
.parent :nth-child(1) {
order: 2;
}
.parent :nth-child(2) {
order: 1;
}
.parent :nth-child(3) {
order: 3;
}
}
You may like to look at grid which will allow you to name areas and assign elements to them.
Then you can redefine the areas when the max-width is at some value.
This saves having to go through all the affected elements and specify their order.
Here's a simple snippet. It puts a background color on each element so you can see which is being allocated to where.
Obviously you'll want to look at exactly the proportions you want the header to take up compared to the paragraph and so on but this is to get you started.
.container {
display: grid;
min-width: 600px;
width: 25%;
aspect-ratio: 1 / 1;
gap: 10px;
grid-template-areas:
'I H'
'I P'
'I P'
'I P';
background: pink;
grid-template-columns: 1fr 1fr;
}
h1 {
grid-area: H;
background: cyan;
}
img {
grid-area: I;
background: magenta;
object-fit: cover;
width: 100%;
height: 100%;
}
p {
grid-area: P;
background: yellow;
}
#media (max-width: 600px) {
.container {
grid-template-areas:
'H'
'I'
'P';
}
}
<div class="container">
<h1>Heading</h1>
<img src="https://picsum.photos/id/1015/200/600">
<p>Paragraph text<br>Paragraph text<br>Paragraph text<br>Paragraph text<br>Paragraph text<br></p>
</div>
The CSS property you're looking for is (quite aptly) named order.
The order property controls the order in which flex items appear
within the flex container, by assigning them to ordinal groups. It
takes a single value, which specifies which ordinal group
the flex item belongs to.
https://www.w3.org/TR/css-flexbox-1/#order-property
So in your example, you would explicitly set the order on all 3 elements, and then within a media query override the order for one/some of the elements to adapt to the "other" layout.
Update: I see you've updated the question but didn't really have any content at all yet. In that case i'd advise going with grid instead of flex. Which is very much alike but has a few features that make it better suited for what you describe.
You could go with something like this:
.parent {
display: grid;
grid: 'heading'
'imagearea'
'content';
}
img { grid-area: imagearea; }
h1 { grid-area: heading; }
p { grid-area: content; }
#media only screen and (max-width: 900px) {
.parent {
grid-template-areas:
'imagearea heading'
'imagearea content';
}
}
/* unrelated CSS; just to show borders */
.parent > * { margin: 0; border: 2px solid black; background-color: #DEFFDE; }
<div class="parent">
<h1>This is a header</h1>
<p>This is some body text that is very interesting</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/2/27/Red_square.svg">
</div>
Thank you for making suggestions that fit my skills.
<div class="parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/2/27/Red_square.svg">
<div class="content">
<h1> This is a header </h1>
<p> This is some body text that is very interesting </p>
</div>
</div>
<style>
.parent {
display:flex;
flex-direction:row;
justify-content: space-between;
}
.content {
display:flex;
flex-direction:colume;
justify-content: space-between;
}
#media screen and (min-width:512px) {
.parent {
display:flex;
flex-direction:colume;
justify-content: space-between;
}
}
</style>
Thanks

Grid element height affected by content image width percentage [duplicate]

This question already has answers here:
Prevent content from expanding grid items
(3 answers)
Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
(1 answer)
Closed 2 years ago.
Edit: Let me clarify! I'm not asking about how to keep the content from flowing out by restricting the size of the container, what I'm looking for is how to properly adjust the size of the content based on the container and why a div with a background image set to cover works, while and img element does not.
I am trying to achieve a standard grid layout with a header, sidebar, content and footer, where the content element would have only a single image as a child, that should fill the entire remaining space. I thought that applying
img {
width: 100%;
height: 100%;
object-fit: cover;
}
would be enough to get the desired result, but it unexpectedly increased the height of the content element. What's even more absurd is that no matter how much I reduce the height of the image, as long as it is measured in percentages, the height of the container keeps depending on the width of the image. See the following pen (or look at the snippets below, but the issue is more apparent in the pen, since there the boxes are visible side-by-side) for example.
https://codepen.io/Isti115/pen/vYGRNpg
Try adjusting the .a img { widht: 100%; } and see how it affects the overall height.
.container {
display: inline-grid;
width: 400px;
height: 300px;
margin: 50px;
grid-template-rows: 75px 1fr 50px;
/* grid-template-rows: 75px minmax(0, 1fr) 50px; */
grid-template-columns: 100px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header {
grid-area: header;
background-color: red;
}
.sidebar {
grid-area: sidebar;
background-color: yellow;
}
.content {
grid-area: content;
background-color: green;
}
.footer {
grid-area: footer;
background-color: blue;
}
.a .content {
/* min-height: 0; */
}
.a img {
width: 100%;
height: 20%;
/* object-fit: cover; */
/* height: 100%; */
}
.b img {
width: 100%;
height: 50px;
/* object-fit: cover; */
}
.c .placeholder {
width: 100%;
height: 100%;
/* background-color: purple; */
background: url("http://lorempixel.com/200/150/cats");
background-size: cover;
}
<div class="container a">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container b">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container c">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<div class="placeholder"></div>
</div>
<div class="footer"></div>
</div>
I have since found a solution by either adding min-height: 0 or using minmax(0, 1fr), but I don't consider those ideal solutions, since I don't see why I couldn't simply take the remaining space that gets assigned to the content div element and place an image inside it that fills it completely without expanding the containers size. For example using a simple div instead of the image and giving it a background works perfectly as intended.
ps.: I know that this might sound similar to some other questions that got answered with max-height: 100%, but I think that there is a more complicated underlying issue that I would like to explore.

Centering an image in CSS grid

I am trying to fix my grid layout.
Firstly, the image should be at the center of .container. I tried using align-self: center;, but that did not work.
The headers and paragraph are really messed up. Before this, the paragraph was pushing down the image so I thought if I gave both of them (and the headers) custom grid-row value, they'd be fixed, but instead, I have all of these elements overlap each other. I need them to be ordered correctly. The paragraph under H3 and H3 below H1.
.container {
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100%;
}
.container img {
grid-column: 1 / 2;
grid-row: 1;
}
.container h1,
h3 {
grid-column: 3;
grid-row: 1;
line-height: 0.35;
}
.container p {
grid-column: 3;
grid-row: 1;
width: 350px;
}
<div class="container">
<h1>-[IFwsI]- Jail</h1>
<h3>More than 40 000 registered players</h3>
<p>The most active, and one of the most successful servers. Jail has a set of rules players need to follow and enjoy the roleplay of inmates vs. CTs scenario</p>
<img src="https://i.imgur.com/epqMIJv.jpg" height="418" width="740" />
</div>
Create columns for the text and image to make it easier to manage the columns.
Take a look at grid-template-columns you can control the widths of each column in myriad ways. I have just set them to 33% width;
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
justify-content: center puts the columns in the horizontal center.
align-items: center aligns the items vertically.
To change the order I've created a new class .column--left with grid-row: 1 to put move it to the first column.
.container {
display: grid;
grid-template-columns: 33% 33%;
justify-content: center;
align-items: center;
grid-gap: 10px;
height: 100vh;
}
.column.column--left {
grid-row: 1;
}
img {
max-width: 100%;
height: auto;
}
<div class="container">
<div class="column">
<h1>-[IFwsI]- Jail</h1>
<h3>More than 40 000 registered players</h3>
<p>The most active, and one of the most successful servers. Jail has a set of rules players need to follow and enjoy the roleplay of inmates vs. CTs scenario</p>
</div>
<div class="column column--left">
<img src="https://i.imgur.com/epqMIJv.jpg" height="418" width="740" />
</div>
</div>
...but instead, I have all of these elements overlap each other.
In your code, you are specifically telling them to overlap each other.
.container h1, h3 {
grid-column: 3;
grid-row: 1;
line-height: 0.35;
}
.container p {
grid-column: 3;
grid-row: 1;
width: 350px;
}
The h1, h3 and p are all placed in column 3, row 1. Why wouldn't they overlap?
Here's another approach that may be useful to you:
.container {
display: grid;
height: 100vh;
align-items: center;
grid-column-gap: 20px;
grid-template-columns: 1fr 2fr 2fr 1fr;
grid-template-areas: " . pic header1 . "
" . pic header3 . "
" . pic ptext . "
" . pic ptext . "
}
.container > h1 { grid-area: header1; }
.container > h3 { grid-area: header3; }
.container > p { grid-area: ptext; }
.container > div { grid-area: pic; }
.container img { width: 100%; object-fit: contain; }
* { margin: 0; }
<div class="container">
<h1>-[IFwsI]- Jail</h1>
<h3>More than 40 000 registered players</h3>
<p>The most active, and one of the most successful servers. Jail has a set of rules players need to follow and enjoy the roleplay of inmates vs. CTs scenario</p>
<div>
<img src="https://i.imgur.com/epqMIJv.jpg" height="418" width="740" />
</div>
</div>
jsFiddle demo
Here's a visualization of the code using Firefox's grid overlay tool.