My responsive CSS grid acts oddly in specific dimensions - In the snippet below, I want the image to occupy the first column (of size auto) and span all rows of the grid for that given breakpoint.
However, the column width is unintentionally wider than the actual image for this particular grid height/width. This weird issue leaves undesired white space on the left and right of the image - space which should be allocated to the 2nd column of width 1fr.
Making the grid wider seems to fix this - the first column immediately changes width to match the image width. (For your convenience I made the outer div resizable.)
(Note:
- the image should not stretch, it's height should be the height of the grid and width should scale proportionately
- the grid min-height should be 100% of its parent element)
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0;
border-style: solid;
}
img {
max-width: 100%;
height: auto;
}
.flex {
display: flex;
}
.grid {
display: grid;
}
.h-full {
height: 100%;
}
.h-min {
height: -moz-min-content;
height: min-content;
}
.max-h-full {
max-height: 100%;
}
.max-h-fit {
max-height: -moz-fit-content;
max-height: fit-content;
}
.min-h-0 {
min-height: 0px;
}
.w-full {
width: 100%;
}
.w-\[20cqw\] {
width: 20cqw;
}
.w-fit {
width: -moz-fit-content;
width: fit-content;
}
.max-w-full {
max-width: 100%;
}
.max-w-fit {
max-width: -moz-fit-content;
max-width: fit-content;
}
.resize {
resize: both;
}
.grid-cols-\[auto_1fr\] {
grid-template-columns: auto 1fr;
}
.grid-rows-\[auto_auto_1fr_auto\] {
grid-template-rows: auto auto 1fr auto;
}
.flex-col {
flex-direction: column;
}
.justify-self-center {
justify-self: center;
}
.overflow-auto {
overflow: auto;
}
.rounded {
border-radius: 0.25rem;
}
.rounded-sm {
border-radius: 0.125rem;
}
.border-4 {
border-width: 4px;
}
.border {
border-width: 1px;
}
.border-purple-800 {
--tw-border-opacity: 1;
border-color: rgb(107 33 168 / var(--tw-border-opacity));
}
.border-sky-500 {
--tw-border-opacity: 1;
border-color: rgb(14 165 233 / var(--tw-border-opacity));
}
.border-neutral-400 {
--tw-border-opacity: 1;
border-color: rgb(163 163 163 / var(--tw-border-opacity));
}
.border-green-500 {
--tw-border-opacity: 1;
border-color: rgb(34 197 94 / var(--tw-border-opacity));
}
.bg-purple-800 {
--tw-bg-opacity: 1;
background-color: rgb(107 33 168 / var(--tw-bg-opacity));
}
.p-3 {
padding: 0.75rem;
}
.p-2 {
padding: 0.5rem;
}
.p-4 {
padding: 1rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.\@container {
container-type: inline-size;
}
@container (min-width: 20rem) {
.\@xs\:row-span-full {
grid-row: 1 / -1;
}
.\@xs\:h-\[min\(100\%_20cqi\)\] {
height: min(100% 20cqi);
}
.\@xs\:h-\[min\(100\%\2c _20cqi\)\] {
height: min(100%, 20cqi);
}
.\@xs\:w-\[20cqw\] {
width: 20cqw;
}
.\@xs\:grid-cols-\[auto_1fr\] {
grid-template-columns: auto 1fr;
}
.\@xs\:grid-rows-\[auto_1fr_auto\] {
grid-template-rows: auto 1fr auto;
}
}
<div
style="width: 405px; height: 160px"
>
<div >
<h4>Example</h4>
<div
>
<img
alt="300"
src="https://via.placeholder.com/300"
width="400"
height="400"
/>
<div>
<div >Featured product</div>
<div >Nutri Ninja Foodi 6L Multi Cooker</div>
</div>
<div >$299</div>
<button
>
Buy
</button>
</div>
</div>
</div>
What I want it to do:
(achieved here for illustrative purposes by hackily by giving 2nd column div width: max-content
, but this causes text not to wrap when it gets too long, whereas I want text to wrap.)
CodePudding user response:
You can try using the grid-template-columns property to specify a fixed width for the grid column that the image is positioned in to resolve this problem.
- No matter how large the image is, this will guarantee that the column will always be the same width. You could try making the first column's width equal to that of the image, or you could use media queries to change the width of the grid's columns based on the size of the screen.
- grid-template-columns: minmax(auto,1fr); will use the minimum and maximum values for auto and 1fr, respectively. The width of the image will be used by the grid rather than the larger value of 1fr.
- Another choice is to remove the max-width: 100% instruction from the img class because the grid already contains it.
- Additionally, it might be advantageous to look for any CSS classes that conflict and modify the height, width, and object-fit as necessary.
(I hope it's helpful for you. Thanks)
CodePudding user response:
The image does not shown because the parent height is fixed and there is no space for image to render, all the other elements occupies spaces.
So the solution is making the parent height to min-content makes your image flexible and responsive
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0;
border-style: solid;
}
.product{
display:flex;
flex-direction:column;
justify-content:space-between;
}
.product_name{
width:95%;
white-space:nowrap;
}
.product_name span{
text-overflow:ellipsis;
overflow:hidden;
display:block;
}
.product button{
margin:5px;
}
img {
width: 100%;
aspect-ratio:1;
}
.flex {
display: flex;
}
.grid {
display: grid;
}
.h-full {
height: 100%;
}
.h-min {
height: -moz-min-content;
height: min-content;
}
.max-h-full {
max-height: 100%;
}
.max-h-fit {
max-height: -moz-fit-content;
max-height: fit-content;
}
.min-h-0 {
min-height: 0px;
}
.w-full {
width: 100%;
}
.w-\[20cqw\] {
width: 20cqw;
}
.w-fit {
width: -moz-fit-content;
width: fit-content;
}
.max-w-full {
max-width: 100%;
}
.max-w-fit {
max-width: -moz-fit-content;
max-width: fit-content;
}
.resize {
resize: both;
}
.grid-cols-\[auto_1fr\] {
grid-template-columns: auto max-content;
}
.grid-rows-\[auto_auto_1fr_auto\] {
grid-template-rows: auto auto 1fr auto;
}
.flex-col {
flex-direction: column;
}
.justify-self-center {
justify-self: center;
}
.overflow-auto {
overflow: auto;
}
.rounded {
border-radius: 0.25rem;
}
.rounded-sm {
border-radius: 0.125rem;
}
.border-4 {
border-width: 4px;
}
.border {
border-width: 1px;
}
.border-purple-800 {
--tw-border-opacity: 1;
border-color: rgb(107 33 168 / var(--tw-border-opacity));
}
.border-sky-500 {
--tw-border-opacity: 1;
border-color: rgb(14 165 233 / var(--tw-border-opacity));
}
.border-neutral-400 {
--tw-border-opacity: 1;
border-color: rgb(163 163 163 / var(--tw-border-opacity));
}
.border-green-500 {
--tw-border-opacity: 1;
border-color: rgb(34 197 94 / var(--tw-border-opacity));
}
.bg-purple-800 {
--tw-bg-opacity: 1;
background-color: rgb(107 33 168 / var(--tw-bg-opacity));
}
.p-3 {
padding: 0.75rem;
}
.p-2 {
padding: 0.5rem;
}
.p-4 {
padding: 1rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.\@container {
container-type: inline-size;
}
@container (min-width: 20rem) {
.\@xs\:row-span-full {
grid-row: 1 / -1;
}
.\@xs\:h-\[min\(100\%_20cqi\)\] {
height: min(100% 20cqi);
}
.\@xs\:h-\[min\(100\%\2c _20cqi\)\] {
height: min(100%, 20cqi);
}
.\@xs\:w-\[20cqw\] {
width: 20cqw;
}
.\@xs\:grid-cols-\[auto_1fr\] {
grid-template-columns: auto 1fr;
}
.\@xs\:grid-rows-\[auto_1fr_auto\] {
grid-template-rows: auto 1fr auto;
}
}
<div
style="width: 405px; height: 200px"
>
<div >
<h4>Example</h4>
<div
>
<img
alt="300"
src="https://via.placeholder.com/300"
/>
<div class='product'>
<div >Featured product</div>
<div >
<span>Nutri Ninja Foodi 6L Multi Cooker</span>
</div>
<div >$299</div>
<button
>
Buy
</button>
</div>
</div>
</div>
</div>