Product Card HTML CSS #7

This product card HTML CSS tutorial shows you how to build a clean editorial-style product card with a best seller badge, a decorative corner frame over the image, a bold product title with a red accent underline, and a price and add to cart row at the bottom. The corner frame effect is created using four absolutely positioned spans. Each shows only two sides of a border, so together they form the four corners of the frame.

Final output:

Best Seller Style No. 4471
product card html css

Aurora.

An 18k yellow gold bridal set. Oval-cut solitaire paired with a full eternity diamond band. Claw-prong setting, high-polish finish.

6,200.00 Add to Cart


Steps for Product Card HTML CSS #7:

1. Link the Hanken Grotesk font from Google Fonts in the head.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">

Let’s start with a .product-card div. Inside it, add a .product-card-top div with two spans for the badge and style number.

<div class="product-card">
    <div class="product-card-top">
        <span>Best Seller</span>
        <span>Style No. 4471</span>
    </div>
</div>

Then reset margins, set Hanken Grotesk as the font family, and define a CSS variable for the red accent color on root so you can reuse it throughout. Style the card with a max-width, a warm off-white background, and a dark border.

* {
    margin: 0;
    box-sizing: border-box;
}
body {
    font-family: "Hanken Grotesk", sans-serif;
}
:root {
    --red: hsl(0, 100%, 42%);
}
.product-card {
    max-width: 24rem;
    background-color: hsla(43, 30%, 95%, 50%);
    border: 1px solid hsl(0, 0%, 4%);
}

Style .product-card-top with flexbox and the justify-content property set to space-between so the badge and style number sit at opposite ends. Add a bottom border to separate it from the image below.

Then style the first span with the red accent color and a small square dot before it using a ::before pseudo-element. Set the position property to absolute on the dot and the position property to relative on the span so the dot sits flush to the left of the text.

.product-card .product-card-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem;
    padding: .675rem 1.25rem;
    border-bottom: 1px solid hsl(0, 0%, 4%);
}
.product-card .product-card-top span {
    font-weight: 400;
    font-size: .675rem;
    line-height: 1.3;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: hsl(49, 5%, 40%);
}
.product-card .product-card-top span:first-child {
    font-weight: 500;
    letter-spacing: 2.16px;
    color: var(--red);
    padding-left: .875rem;
    position: relative;
}
.product-card .product-card-top span:first-child::before {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    content: "";
    width: .375rem;
    height: .375rem;
    background-color: var(--red);
}

Output:

Best Seller Style No. 4471

2. Add the .img-wrapper div after .product-card-top. Inside it, add the product image and four corner span elements.

<div class="img-wrapper">
    <img src="rings.png" alt="">
    <span class="corner-1"></span>
    <span class="corner-2"></span>
    <span class="corner-3"></span>
    <span class="corner-4"></span>
</div>

Set the position property to relative on .img-wrapper so the corner spans can be placed inside it using absolute positioning. Give it a fixed height and set the object fit property to cover on the image so it fills the wrapper without stretching. Each corner span only shows two sides of a border using selective border widths, so together they create a decorative frame inside the image corners.

.product-card .img-wrapper {
    width: 100%;
    height: 18rem;
    position: relative;
}
.product-card .img-wrapper img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.product-card .corner-1,
.product-card .corner-2,
.product-card .corner-3,
.product-card .corner-4 {
    position: absolute;
    width: .75rem;
    height: .75rem;
    border-style: solid;
    border-color: #0A0A0A;
}
.product-card .corner-1 {
    left: .5rem;
    top: .5rem;
    border-width: 1px 0px 0px 1px;
}
.product-card .corner-2 {
    right: .5rem;
    top: .5rem;
    border-width: 1px 1px 0px 0px;
}
.product-card .corner-3 {
    left: .5rem;
    bottom: .5rem;
    border-width: 0px 0px 1px 1px;
}
.product-card .corner-4 {
    right: .5rem;
    bottom: .5rem;
    border-width: 0px 1px 1px 0px;
}

Output:

Best Seller Style No. 4471
product card html css step 2

3. Add the .product-card-body div after the image. Inside it, add the product title heading and a description paragraph.

<div class="product-card-body">
    <h3 class="product-title">Aurora<span>.</span></h3>
    <p class="product-description">An 18k yellow gold bridal set. Oval-cut solitaire paired with a full eternity diamond band. Claw-prong setting, high-polish finish.</p>
</div>

Add top and bottom borders on .product-card-body using the border block property to visually separate it from the image above and the price row below. Style the title with a heavy font weight, a tight line height, and uppercase text.

Set the position property to relative on the title so the short red underline can be placed below it using a ::after pseudo-element. The span inside the title gets the red accent color so the period stands out as a design detail. Style the description with a smaller muted font for a clear visual hierarchy.

.product-card .product-card-body {
    padding: 1.25rem;
    border-block: 1px solid hsl(0, 0%, 4%);
}
.product-card .product-title {
    font-weight: 900;
    font-size: 2rem;
    line-height: .9;
    letter-spacing: -0.8px;
    text-transform: uppercase;
    position: relative;
    padding-bottom: .5rem;
    margin-bottom: .5rem;
}
.product-card .product-title span {
    color: var(--red);
}
.product-card .product-title::after {
    position: absolute;
    bottom: 0;
    left: 0;
    content: "";
    width: 34px;
    height: 3px;
    background: var(--red);
}
.product-card .product-description {
    font-size: .875rem;
    line-height: 1.5;
    color: hsl(49, 5%, 40%);
}

Output:

Best Seller Style No. 4471
product card html css step 2

Aurora.

An 18k yellow gold bridal set. Oval-cut solitaire paired with a full eternity diamond band. Claw-prong setting, high-polish finish.

4. Finally, add the .product-card-bottom div with the price span and an “Add to Cart” link.

<div class="product-card-bottom">
    <span class="product-price">6,200.00</span>
    <a href="#">
        <span>Add to Cart</span>
        <svg width="13" height="5" viewBox="0 0 13 5" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M9.45052 4.21172C9.63052 3.82772 9.80452 3.49172 9.97252 3.20372C10.1525 2.91572 10.3265 2.67572 10.4945 2.48372H0.000515878V1.72772H10.4945C10.3265 1.52372 10.1525 1.27772 9.97252 0.989718C9.80452 0.701718 9.63052 0.371718 9.45052 -0.000281632H10.0805C10.8365 0.875719 11.6285 1.52372 12.4565 1.94372V2.26772C11.6285 2.67572 10.8365 3.32372 10.0805 4.21172H9.45052Z" fill="#F7F5F0" />
        </svg>
    </a>
</div>

Use flexbox with the justify-content property set to space-between and the align-items property set to stretch on .product-card-bottom so the price and button fill the full height of the row. Style the price with a heavy font weight and a large font size. Style the “Add to Cart” link with a dark background and a light text color, since it acts as the primary call to action on the card.

.product-card .product-card-bottom {
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    gap: .5rem;
}
.product-card .product-price {
    font-weight: 900;
    font-size: 1.563rem;
    line-height: 1;
    letter-spacing: -0.64px;
    padding: 1.25rem;
    display: inline-block;
}
.product-card .product-card-bottom a {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: .5rem;
    text-decoration: none;
    padding: 1.25rem 2.5rem;
    font-weight: 500;
    font-size: .675rem;
    line-height: 1;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: hsl(43, 30%, 95%);
    background-color: hsl(0, 0%, 4%);
}

Output:

Best Seller Style No. 4471
product card html css

Aurora.

An 18k yellow gold bridal set. Oval-cut solitaire paired with a full eternity diamond band. Claw-prong setting, high-polish finish.

6,200.00 Add to Cart


Final Output Code for HTML CSS Product Card #7:

HTML

<div class="product-card">
    <div class="product-card-top">
        <span>Best Seller</span>
        <span>Style No. 4471</span>
    </div>
    <div class="img-wrapper">
        <img src="rings.png" alt="">
        <span class="corner-1"></span>
        <span class="corner-2"></span>
        <span class="corner-3"></span>
        <span class="corner-4"></span>
    </div>
    <div class="product-card-body">
        <h3 class="product-title">Aurora<span>.</span></h3>
        <p class="product-description">An 18k yellow gold bridal set. Oval-cut solitaire paired with a full eternity
            diamond band. Claw-prong
            setting, high-polish finish.</p>
    </div>
    <div class="product-card-bottom">
        <span class="product-price">6,200.00</span>
        <a href="#"><span>Add to Cart</span>
            <svg width="13" height="5" viewBox="0 0 13 5" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path
                    d="M9.45052 4.21172C9.63052 3.82772 9.80452 3.49172 9.97252 3.20372C10.1525 2.91572 10.3265 2.67572 10.4945 2.48372H0.000515878V1.72772H10.4945C10.3265 1.52372 10.1525 1.27772 9.97252 0.989718C9.80452 0.701718 9.63052 0.371718 9.45052 -0.000281632H10.0805C10.8365 0.875719 11.6285 1.52372 12.4565 1.94372V2.26772C11.6285 2.67572 10.8365 3.32372 10.0805 4.21172H9.45052Z"
                    fill="#F7F5F0" />
            </svg>

        </a>
    </div>
</div>

CSS

* {
    margin: 0;
    box-sizing: border-box;
}
body {
    font-family: "Hanken Grotesk", sans-serif;
}
:root {
    --red: hsl(0, 100%, 42%);
}
.product-card {
    max-width: 24rem;
    background-color: hsla(43, 30%, 95%, 50%);
    border: 1px solid hsl(0, 0%, 4%);
}
.product-card .product-card-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem;
    padding: .675rem 1.25rem;
    border-bottom: 1px solid hsl(0, 0%, 4%);
}
.product-card .product-card-top span {
    font-weight: 400;
    font-size: .675rem;
    line-height: 1.3;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: hsl(49, 5%, 40%);
}
.product-card .product-card-top span:first-child {
    font-weight: 500;
    letter-spacing: 2.16px;
    color: var(--red);
    padding-left: .875rem;
    position: relative;
}
.product-card .product-card-top span:first-child::before {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    content: "";
    width: .375rem;
    height: .375rem;
    background-color: var(--red);
}
.product-card .img-wrapper {
    width: 100%;
    height: 18rem;
    position: relative;
}
.product-card .img-wrapper img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.product-card .corner-1,
.product-card .corner-2,
.product-card .corner-3,
.product-card .corner-4 {
    position: absolute;
    width: .75rem;
    height: .75rem;
    border-style: solid;
    border-color: #0A0A0A;
}
.product-card .corner-1 {
    left: .5rem;
    top: .5rem;
    border-width: 1px 0px 0px 1px;
}
.product-card .corner-2 {
    right: .5rem;
    top: .5rem;
    border-width: 1px 1px 0px 0px;
}
.product-card .corner-3 {
    left: .5rem;
    bottom: .5rem;
    border-width: 0px 0px 1px 1px;
}
.product-card .corner-4 {
    right: .5rem;
    bottom: .5rem;
    border-width: 0px 1px 1px 0px;
}
.product-card .product-card-body {
    padding: 1.25rem;
    border-block: 1px solid hsl(0, 0%, 4%);
}
.product-card .product-title {
    font-weight: 900;
    font-size: 2rem;
    line-height: .9;
    letter-spacing: -0.8px;
    text-transform: uppercase;
    position: relative;
    padding-bottom: .5rem;
    margin-bottom: .5rem;
}
.product-card .product-title span {
    color: var(--red);
}
.product-card .product-title::after {
    position: absolute;
    bottom: 0;
    left: 0;
    content: "";
    width: 34px;
    height: 3px;
    background: var(--red);
}
.product-card .product-description {
    font-size: .875rem;
    line-height: 1.5;
    color: hsl(49, 5%, 40%);
}
.product-card .product-card-bottom {
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    gap: .5rem;
}
.product-card .product-price {
    font-weight: 900;
    font-size: 1.563rem;
    line-height: 1;
    letter-spacing: -0.64px;
    padding: 1.25rem;
    display: inline-block;
}
.product-card .product-card-bottom a {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: .5rem;
    text-decoration: none;
    padding: 1.25rem 2.5rem;
    font-weight: 500;
    font-size: .675rem;
    line-height: 1;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: hsl(43, 30%, 95%);
    background-color: hsl(0, 0%, 4%);
}

If you have any doubts or stuck somewhere, you can reach out through Coding Yaar's Discord server.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Most Voted
Newest Oldest
0
Would love your thoughts, please comment.x
()
x