As a part of a home interview assignment, I was asked to build a responsive e-commerce mini website site based on a Figma design I got.
Create a CSS file with media queries, and for the card container give a display of grid. On each resolution, change the elements' columns and raws they span, to copy the desired layout.
On a tablet, they wish to show 3 products on each line and to make the product card look like the mobile single card. See image below
The problem is I ordered the card to change based on the resolution, so I kind of need to find a way to tell the card to look like it looks on mobile.
I saw it is possible doing it with an experimental technology which is called "container query", meaning that the size of the container will decide the element CSS and not the screen size.
Another possibility from what I've read online is that SASS allows you to create a class and tell it to behave differently on different resolutions (create the media queries inside the class essentially).
@import url("https://rsms.me/inter/inter.css");
/* ------------------- Variables ------------------------ */
:root {
font-family: "Inter", sans-serif;
/* btn background colors */
--bg-dark-blue: #0b76e0;
--bg-blue: #55a0ea;
--bg-light-blue: #d5eaff;
--bg-baby-blue: #88bdf1;
--bg-orange: #ff5c00;
--bg-dark-orange: #b04000;
/* text colors */
--text-semi-gray: #7b8997;
--text-medium-gray: #9fa9b3;
--text-bold-gray: #626e79;
--text-heavy-gray: #2c384a;
--text-xtra-bold-gray: #55626e;
--text-red: #df0923;
--text-blue: #0b76e0;
--text-white: #ffffff;
}
* > * {
box-sizing: border-box;
padding: 0;
margin: 0;
}
ul {
margin-left: 11px;
}
a {
text-decoration: none;
}
body {
background-color: #f2f4f7;
}
main {
margin: 40px auto;
max-width: 1024px;
background-color: #eeeff1;
padding: 25px;
}
h2 {
font-size: 20px;
color: var(--text-xtra-bold-gray);
line-height: 24px;
}
/* ------------------- /Variables ------------------------ */
/* ------------------- Global Classes ------------------------ */
.btn {
border: none;
background-color: transparent;
cursor: pointer;
border-radius: 12px;
}
.bg-dark-blue {
background-color: var(--bg-dark-blue);
}
.bg-blue {
background-color: var(--bg-blue);
}
.bg-light-blue {
background-color: var(--bg-light-blue);
}
.text-gray {
color: var(--text-xtra-bold-gray);
}
.text-semi-gray {
color: var(--text-semi-gray);
}
.text-heavy-gray {
color: var(--text-heavy-gray);
}
.text-medium-gray {
color: var(--text-medium-gray);
}
.text-red {
color: var(--text-red);
}
.text-blue {
color: var(--text-blue);
}
.text-white {
color: var(--text-white);
}
/* ------------------- /Global Classes ------------------------ */
/* ------------------- Product Ticket ------------------------ */
.card {
width: 100%;
line-height: 140%;
background: #ffffff;
box-shadow: 0px 51px 114px rgba(199, 199, 199, 0.15),
0px 15.375px 34.3677px rgba(199, 199, 199, 0.0895633),
0px 6.38599px 14.2746px rgba(199, 199, 199, 0.0605927),
0px 2.30969px 5.16283px rgba(199, 199, 199, 0.0352376);
border-radius: 12px;
position: relative;
gap: 5px;
letter-spacing: 0.2px;
margin: 45px auto;
}
.ribbon-underlay {
box-shadow: 4px 4px 15px rgb(26 35 126 / 20%);
position: absolute;
width: 7px;
height: 6.5px;
top: 10px;
left: -5px;
transform: rotate(45deg);
z-index: -1;
}
.ribbon-underlay.best-choice-underlay {
background-color: var(--bg-dark-orange);
}
.ribbon-underlay.best-value-underlay {
background-color: var(--bg-baby-blue);
}
.ribbon-overlay {
color: var(--text-white);
content: "";
width: 140px;
height: 32px;
position: absolute;
top: -19px;
left: -7px;
box-shadow: 4px 4px 15px rgb(26 35 126 / 20%);
z-index: 1;
border-radius: 0px 8px 8px 0px;
}
.ribbon-overlay.best-choice-overlay {
background-color: var(--bg-orange);
}
.ribbon-overlay.best-value-overlay {
background-color: var(--bg-light-blue);
color: var(--text-blue);
}
.ribbon-overlay .content {
display: flex;
justify-content: center;
height: 100%;
gap: 8px;
}
.ribbon-overlay .content > * {
align-self: center;
}
.product .product-image img {
max-width: 100%;
}
.product .product-rating {
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-self: center;
max-width: 49px;
}
.product .product-rating .numeric-rating {
text-align: center;
line-height: 33.6px;
}
.product .product-rating .stars-rating {
display: flex;
flex: 1;
justify-content: center;
}
.product .product-rating .info {
color: var(--text-medium-gray);
position: absolute;
right: 0;
}
.product .product-rating .numeric-rating {
color: var(--text-xtra-bold-gray);
font-weight: 700;
}
.product .product-rating .stars-rating {
color: var(--bg-dark-blue);
}
.product .product-title {
color: var(--text-xtra-bold-gray);
}
.product .product-discount {
background-color: var(--bg-blue);
color: white;
border-radius: 4px;
padding: 2px 4px;
max-width: max-content;
}
.product .product-company {
color: var(--text-bold-gray);
}
.product .product-view-deal {
background-color: var(--bg-dark-blue);
color: var(--text-white);
}
.product .product-vendor {
color: var(--text-xtra-bold-gray);
}
.product .product-show-more {
color: var(--text-xtra-bold-gray);
cursor: pointer;
display: flex;
}
.hidden {
display: none !important;
}
.rotate {
transform: rotate(180deg);
}
.product .product-info .highlights .title {
color: var(--text-xtra-bold-gray);
margin: 10px 0 8px 0;
}
.product .product-info .highlights ul li {
color: var(--text-semi-gray);
text-decoration: dotted;
}
.product .product-info .product-price {
}
.product .product-info .product-price .current {
color: var(--text-heavy-gray);
}
.product .product-info .product-price .original {
color: var(--text-medium-gray);
text-decoration: line-through;
}
.product .product-info .product-price .discount {
color: var(--text-red);
}
.product .product-info .vendor-container {
/* display: flex;
justify-content: space-around; */
}
.product .product-info .vendor-container > * {
/* flex: 1 1 100%; */
}
.product .product-info .vendor-container img {
width: 100%;
}
.product .product-info .vendor-container .view-btn {
border: 1px solid var(--bg-dark-blue);
color: var(--bg-dark-blue);
}
/* ------------------- /Product Ticket ------------------------ */
/* ------------------- Media Query ------------------------ */
/* Media Query for Mobile Devices */
@media (max-width: 480px) {
.card {
display: grid;
padding: 20px;
grid-template-columns: repeat(4, minmax(10px, 1fr));
grid-template-rows: repeat(7, minmax(min-content, max-content));
}
.product .product-image {
grid-column: 2 / 4;
grid-row: 1;
-ms-grid-column-span: 3;
justify-content: center;
margin-top: 22px;
}
.product .product-image img {
width: 160px;
}
.product .product-rating {
grid-column: 4 / 5;
grid-row: 1;
align-self: end;
bottom: 10px;
}
.product .product-rating .info > * {
font-size: 8.96px;
}
.product .product-rating .numeric-rating {
font-size: 24px;
}
.product .product-rating .stars-rating > * {
font-size: 8.1px;
}
.product .product-discount {
font-size: 12px;
font-weight: 600;
}
.product .product-title {
font-size: 14px;
font-weight: 600;
line-height: 19.6px;
grid-row: 4;
grid-column: 1/-1;
}
.product .product-discount {
font-size: 12px;
font-weight: 500;
grid-column: 1 / -1;
}
.product .product-company {
font-size: 14px;
font-weight: 400;
grid-column: 1/5;
grid-row: 2;
text-align: center;
}
.product .product-view-deal {
font-size: 16px;
font-weight: 500;
padding: 4px 40px;
width: 100%;
height: 42px;
margin: 15px 0 10px;
grid-row: 5;
grid-column: 1/-1;
}
.product .product-vendor {
font-size: 14px;
font-weight: 400;
text-align: left;
grid-row: 6;
grid-column: 1/3;
text-align: center;
}
.product .product-show-more {
justify-content: right;
font-size: 14px;
font-weight: 400;
text-align: right;
grid-row: 6;
grid-column: 3/5;
}
.product .product-info {
display: grid;
grid-column: 1/-1;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, minmax(min-content, max-content));
gap: 10px;
}
.product .product-info .highlights {
font-weight: 700;
font-size: 18px;
grid-column: 1/-1;
}
.product .product-info .highlights .title {
font-size: 18px;
font-weight: 700;
margin: 10px 0 8px 0;
}
.product .product-info .highlights ul {
line-height: 16.8px;
}
.product .product-info .highlights ul li {
font-weight: 400;
font-size: 12px;
}
.product .product-info .product-price {
grid-column: 1/-1;
display: flex;
gap: 10px;
justify-content: center;
}
.product .product-info .product-price .current {
font-weight: 600;
font-size: 14px;
}
.product .product-info .product-price .original {
font-weight: 400;
font-size: 14px;
}
.product .product-info .product-price .discount {
font-weight: 400;
font-size: 10px;
}
.product .product-info .vendor-container {
grid-column: 1/-1;
display: grid;
grid-template-columns: repeat(4, 1fr);
justify-items: center;
}
.product .product-info .vendor-container img {
align-self: center;
width: 65.83px;
grid-column: 1/3;
}
.product .product-info .vendor-container .view-btn {
width: 152px;
height: 32px;
grid-column: 3/5;
}
}
/* Media Query for low resolution Tablets, Ipads */
@media (min-width: 481px) and (max-width: 768px) {
.card {
display: grid;
padding: 20px 10px 10px;
column-gap: 15px;
grid-template-columns: 1fr 2fr max-content max-content;
grid-template-rows: repeat(5, minmax(min-content, max-content));
}
.hide-discount {
visibility: hidden;
}
.ribbon-overlay {
font-size: 16px;
font-weight: 600px;
}
.product .product-image {
grid-column: 1 / 2;
grid-row: 1/5;
}
.product .product-rating {
grid-column: 3/4;
grid-row: 1/5;
}
.product .product-rating .info > * {
font-size: 9.05px;
}
.product .product-rating .numeric-rating {
font-size: 20px;
}
.product .product-rating .stars-rating > * {
font-size: 8.19px;
}
.product .product-title {
font-size: 14px;
font-weight: 500;
line-height: 19.6px;
grid-column: 2/3;
grid-row: 1/2;
height: 40px;
overflow: hidden;
}
.product .product-discount {
font-size: 12px;
font-weight: 600;
grid-column: 2/3;
grid-row: 3/4;
}
.product .product-company {
font-size: 12px;
font-weight: 400;
grid-column: 2/3;
grid-row: 2/3;
}
.product .product-view-deal {
font-size: 14px;
font-weight: 700;
padding: 4px 40px;
min-width: 170px;
min-height: 36px;
grid-row: 2/4;
align-self: center;
}
.product .product-vendor {
text-align: center;
font-size: 12px;
grid-column: 4/5;
grid-row: 4/5;
}
.product .product-show-more {
font-size: 12px;
font-weight: 500;
grid-column: 2/3;
grid-row: 4/5;
}
.product .product-info {
display: grid;
grid-column: 1/-1;
grid-template-columns: 3fr 1fr;
grid-template-rows: 4fr 1fr;
row-gap: 10px;
column-gap: 20px;
}
.product .product-info .highlights {
font-weight: 600;
font-size: 18px;
grid-column: 1/2;
grid-row: 1/3;
}
.product .product-info .highlights ul li {
font-weight: 400;
font-size: 14px;
}
.product .product-info .product-price {
align-self: end;
display: flex;
flex-wrap: wrap;
row-gap: 5px;
grid-column: 2/3;
grid-row: 1/2;
}
.product .product-info .product-price .current {
font-weight: 600;
font-size: 16px;
flex: 1 1 100%;
/* flex-grow: 1; */
}
.product .product-info .product-price .original {
font-weight: 400;
font-size: 14px;
/* flex-grow: 1; */
flex: 1 1 50%;
}
.product .product-info .product-price .discount {
font-weight: 400;
font-size: 12px;
/* flex-grow: 1; */
flex: 1 1 50%;
}
.product .product-info .vendor-container {
align-self: end;
display: flex;
grid-column: 2/3;
grid-row: 2/3;
gap: 15px;
}
.product .product-info .vendor-container img {
min-width: 0;
height: 100%;
flex: 3 3;
align-self: center;
}
.product .product-info .vendor-container .view-btn {
flex: 5 5;
width: 94px;
height: 36px;
}
/* ------------------- Related Deals ------------------------ */
.related-deals {
display: grid;
grid-template-columns: repeat(12, 1fr);
}
.col-md-4 {
grid-column: 1 / span 4;
}
/* ------------------ /Related Deals ------------------------ */
}
/* Media Query for Tablets Ipads portrait mode */
@media (min-width: 768px) {
.card {
display: grid;
padding: 20px 15px 10px;
column-gap: 15px;
grid-template-columns: 0.5fr 1fr 2fr max-content max-content;
grid-template-rows: repeat(5, minmax(min-content, max-content));
}
.product .product-image {
grid-column: 2 / 3;
grid-row: 1/5;
}
.product .product-rating {
grid-column: 4/5;
grid-row: 1/5;
max-width: 75px;
}
.product .product-rating .info > * {
font-size: 12.25px;
}
.product .product-rating .numeric-rating {
font-size: 32.8165px;
}
.product .product-rating .stars-rating > * {
font-size: 11.08px;
}
.product .product-title {
font-size: 16px;
font-weight: 600;
line-height: 22.4px;
grid-column: 3/4;
grid-row: 1/2;
}
.product .product-discount {
font-size: 14px;
font-weight: 500;
grid-column: 3/4;
grid-row: 3/4;
}
.product .product-company {
font-size: 14px;
font-weight: 500;
grid-column: 3/4;
grid-row: 2/3;
}
.product .product-view-deal {
font-size: 16px;
font-weight: 700;
padding: 10px 80px;
min-width: 170px;
min-height: 36px;
grid-row: 2/4;
grid-column: 5/6;
align-self: center;
}
.product .product-vendor {
font-size: 14px;
font-weight: 400;
grid-column: 5/6;
grid-row: 4/5;
justify-content: start;
text-align: left;
}
.product .product-show-more {
font-size: 14px;
font-weight: 600;
grid-column: 5/6;
grid-row: 4/5;
justify-content: end;
}
.product .product-info {
grid-column: 2/-1;
grid-row: 5/6;
display: grid;
grid-template-rows: 4fr 1fr;
gap: 10px;
grid-template-columns: 2fr 2fr 1fr 1fr;
}
.product .product-info .highlights {
font-weight: 700;
font-size: 20px;
grid-column: 1/3;
grid-row: 1/3;
}
.product .product-info .highlights ul li {
font-weight: 400;
font-size: 14px;
}
.product .product-info .product-price {
align-self: end;
display: flex;
flex-wrap: wrap;
gap: 12px;
grid-column: 4/5;
grid-row: 1/3;
margin-bottom: 25%;
}
.product .product-info .product-price .current {
font-weight: 600;
font-size: 24px;
flex: 1 0 100%;
}
.product .product-info .product-price .original {
font-weight: 400;
font-size: 18px;
}
.product .product-info .product-price .discount {
font-weight: 400;
font-size: 14px;
}
.product .product-info .vendor-container {
align-self: end;
grid-column: 4/5;
grid-row: 1/3;
gap: 15px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.product .product-info .vendor-container img {
max-width: 65px;
}
.product .product-info .vendor-container .view-btn {
width: 246px;
height: 44px;
font-weight: 700;
}
}
/* ------------------- /Media Query ------------------------ */
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200"
/>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<script defer src="./index.js"></script>
<main>
<div class="product card">
<div class="ribbon">
<div class="ribbon-overlay best-choice-overlay">
<div class="content">
<i class="fa-solid fa-trophy"></i>
<span>Best Choice</span>
</div>
</div>
<div class="ribbon-underlay best-choice-underlay"></div>
</div>
<div class="product-image">
<img src="https://images-na.ssl-images-amazon.com/images/I/916NVBBT0mS.__AC_SY300_SX300_QL70_FMwebp_.jpg" alt="" />
</div>
<div class="product-rating">
<div class="info">
<span class="material-symbols-outlined"> info </span>
</div>
<div class="numeric-rating">9.8</div>
<div class="stars-rating">
<span class="material-symbols-outlined"> star </span>
<span class="material-symbols-outlined"> star </span>
<span class="material-symbols-outlined"> star </span>
<span class="material-symbols-outlined"> star </span>
<span class="material-symbols-outlined"> star_half </span>
</div>
</div>
<div class="product-title">
Sony X95J 85 Inch TV: BRAVIA XR Full Array LED 4K Ultra HD Smart
Google TV
</div>
<div class="product-discount">50% OFF</div>
<div class="product-company">SONY</div>
<button class="product-view-deal btn">View Deal</button>
<div class="product-vendor">On Amazon</div>
<div class="product-show-more">
Show more
<span class="material-symbols-outlined expand_more">
expand_more
</span>
</div>
<div class="product-info hidden">
<div class="highlights">
<h3 class="title">Main Hightlights</h3>
<ul>
<li>
4K Ultra HD (2160p resolution): Enjoy breathtaking 4K movies and
TV shows at 4 times the resolution of Full HD, and upscale your
current content to Ultra HD-level picture quality.
</li>
<li>
Voice remote with Alexa: Use the sound of your voice to do
everything a regular remote would do: Switch streaming services,
inputs, channels and much more.
</li>
<li>
Access thousands of shows with Fire TV - Watch over 1 million
streaming movies and TV episodes with access to thousands of
channels, apps and Alexa skills, including Apple TV+, Disney+,
Hulu, Netflix, Prime Video, Sling TV, YouTube and other services
right from this TV.
</li>
<li>
Hands-free control: Pair with your Amazon Echo and go
hands-free, controlling volume, search, channels and more.
</li>
</ul>
</div>
<div class="product-price">
<div class="current">$99.00</div>
<div class="original">$199.00</div>
<div class="discount">(26% off)</div>
</div>
<div class="vendor-container">
<img src="https://pngimg.com/uploads/amazon/amazon_PNG24.png" />
<button class="view-btn btn">View</button>
</div>
</div>
</div>
<div class="related-deals">
<h2>Related Deals You Might Like For Tv</h2>
</div>
</main>
<script src="https://kit.fontawesome.com/ead62a3458.js"></script>
</body>
</html>
So the problem was that my Card class was changing as I ordered it according to the screen resolution, but I wanted it to change according to the Card container resolution so that on a tablet, I can spread 3 small (mobile layout) cards. I know I could have created a new class and named it small-card, but I wanted to give the same class name for all cards.
The solution for using the same class but changing its CSS properties without duplicating the same properties to a new class was to use SASS.
SASS has many capabilities, one of them is called mixins -
Mixins allow you to define styles that can be re-used throughout your stylesheet. They make it easy to avoid using non-semantic classes like .float-left, and to distribute collections of styles in libraries.
Also, one of SASS's great capabilities is to allow you to put the media queries inside the class, which allowed me to keep my card class well-organized.
Here's the improved code, written with SASS:
@mixin small-card() {
// ...
}
@mixin medium-card() {
// ...
}
@mixin large-card() {
// ...
}
@media (max-width: 480px) {
.card {
@include small-card();
}
}
@media (min-width: 481px) and (max-width: 768px) {
.card {
@include medium-card();
}
}
@media (min-width: 768px) {
.card {
@include large-card();
}
}
.related-deals {
display: grid;
grid-template-columns: repeat(3, 1fr);
.card {
@include small-card();
margin: auto;
}
}