---
id: 66eaddd04a9e533fba689001
title: Design a Blog Post Card
challengeType: 25
dashedName: lab-blog-post-card
demoType: onClick
---

# --description--

In this lab, you'll practice how to style backgrounds and borders by creating a blog post card.

**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.

**User Stories:**

1. You should have a `div` element with a class of `blog-post-card` to hold all of your card elements.
2. Within the `.blog-post-card` element, you should have an image element with a valid `alt` attribute and text, and a class of `post-img`. You can use `https://cdn.freecodecamp.org/curriculum/labs/cover-photo.jpg` for the `src` attribute of the image.
3. You should have a `div` with a class of `post-content` within the `.blog-post-card` element with the following:
    - An `h2` element with a class of `post-title` and text for the title of your blog post.
    - A `p` element with a class of `post-excerpt` and text to summarize your blog post.
    - An `a` element with a class of `read-more` with the text `Read More`.
4. You should apply the following styles to the `.blog-post-card` element:
    - A white background.
    - Rounded corners.
    - A width of your choice.
    - The text alignment of your choice.
5. The `.post-img` element should be styled so that the image fills the card's entire width and has a bottom border.
6. The `.post-content` element should be styled so that there is padding inside the card.
7. The `.post-title` and `.post-excerpt` elements should have a text color other than the default and margins on all sides.
8. The `.read-more` element should be styled like a button and have:
    - A text color other than the default.
    - A background color.
    - Margins on all sides.
    - Padding on all sides.
    - Rounded corners.
    - A `display` property set to `inline-block`.
    - A hover effect that changes its background color.

**Note:** Be sure to link your stylesheet in your HTML and apply your CSS.

# --hints--

You should have a `div` with a class of `blog-post-card`.

```js
assert.exists(document.querySelector("div.blog-post-card"));
```

You should have an `img` element with a `class` of `post-img`. Make sure your image has an `alt` attribute with text and a `src` attribute with a value.

```js
const card = document.querySelector("div.blog-post-card");
assert.exists(card);

const img = card.querySelector("img.post-img");
assert.exists(img);
assert.isString(img.alt);
assert.isNotEmpty(img.alt);
assert.isTrue(img.hasAttribute("src"));
assert.isNotEmpty(img.getAttribute("src"));
```

You should have a `div` with class of `post-content`.

```js
const card = document.querySelector("div.blog-post-card");
assert.exists(card);
const content = card.querySelector("div.post-content");
assert.exists(content);
```

You should have an `h2` element with a class of `post-title`. Make sure it has some text content for the title of your blog post.

```js
const card = document.querySelector("div.blog-post-card");
assert.exists(card);

const content = card.querySelector("div.post-content");
assert.exists(content);

const postTitle = content.querySelector("h2.post-title");
assert.exists(postTitle);
assert.isString(postTitle.textContent);
assert.isNotEmpty(postTitle.textContent);
```

You should have a `p` with a class of `post-excerpt`. Make sure it has some text content to summarize your blog post.

```js
const card = document.querySelector("div.blog-post-card");
assert.exists(card);

const content = card.querySelector("div.post-content");
assert.exists(content);

const postExcerpt = content.querySelector("p.post-excerpt");
assert.exists(postExcerpt);
```

You should have an `a` element with a `class` of `read-more`.

```js
const card = document.querySelector("div.blog-post-card");
assert.exists(card);

const content = card.querySelector("div.post-content");
assert.exists(content);

const readMore = content.querySelector("a.read-more");
assert.exists(readMore);
```

Your `.read-more` element should have the text `Read More`.

```js
const el = document.querySelector("div.post-content a.read-more");
assert.exists(el);
assert.strictEqual(el.textContent.trim(), "Read More");
```

Your `.blog-post-card` element should have a `border-radius` property with a value (should not be `0` or a negative value).

```js
const card = document.querySelector('.blog-post-card');
assert.exists(card);

const borderRadius = getComputedStyle(card).borderRadius;
assert.isAbove(parseInt(borderRadius), 0);
```

Your `.blog-post-card` element should have a white background.

```js
const card = document.querySelector('.blog-post-card');
assert.exists(card);

const backgroundColor = getComputedStyle(card).backgroundColor;
const whiteColors = ['rgb(255, 255, 255)', 'rgba(255, 255, 255, 1)', '#ffffff', '#fff', 'white'];

assert.oneOf(backgroundColor.toLowerCase(), whiteColors);
```

You should target `.blog-post-card` and set its `width` property.

```js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".blog-post-card")?.getPropertyValue("width"));
```

You should target `.blog-post-card` and set its `text-align` property.

```js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".blog-post-card")?.getPropertyValue("text-align"));
```

You should target `.post-content` and set its `padding` property.

```js
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".post-content")?.getPropertyValue("padding"));
```

Your `.read-more` element should have a hover effect.

```js
const link = document.querySelector('.read-more');
assert.exists(link);

const d = new __helpers.CSSHelp(document).getStyle('.read-more:hover');
assert.isNotEmpty(d.backgroundColor);
```

You should target `.read-more` and set its `color` property.

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMoreTextColor = getComputedStyle(readMore).color;
assert.notStrictEqual(readMoreTextColor, 'rgba(0, 0, 0, 0)');
```

You should target `.read-more` and set its `background-color` property.

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMoreBackgroundColor = getComputedStyle(readMore).backgroundColor;
assert.notStrictEqual(readMoreBackgroundColor, 'rgba(0, 0, 0, 0)');
```

You should target `.read-more` and set its `margin` property. 

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMoreMargin = getComputedStyle(readMore).marginTop;
assert.notStrictEqual(readMoreMargin, '0px');
```

You should target `.read-more` and set its `display` property. 

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMoreDisplay = getComputedStyle(readMore).display;
assert.strictEqual(readMoreDisplay, 'inline-block');
```

You should target `.read-more` and set its `border-radius` property. 

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMoreBorderRadius = getComputedStyle(readMore).borderRadius;
assert.notStrictEqual(readMoreBorderRadius, '0px');
```

You should target `.read-more` and set its `padding` property. 

```js
const readMore = document.querySelector('.read-more');
assert.exists(readMore);

const readMorePadding = getComputedStyle(readMore).padding;
assert.notStrictEqual(readMorePadding, '0px');
```

Your `.post-img` element should fill the card's `width`.

```js
const postImg = document.querySelector('.post-img');
assert.exists(postImg);

const imgWidth = getComputedStyle(postImg).width;
const cardWidth = getComputedStyle(postImg.parentElement).width;
assert.closeTo(Number(imgWidth.replace(/px/ig, "")), Number(cardWidth.replace(/px/ig, "")), 15);
```

Your `.post-img` element should have a `border-bottom` value.

```js
const postImg = document.querySelector('.post-img');
assert.exists(postImg);

const imgBorderBottom = getComputedStyle(postImg).borderBottomWidth;
assert.notStrictEqual(imgBorderBottom, '0px');
```

Your `.post-title` and `.post-excerpt` elements should have margins and non-default text colors.

```js
const title = document.querySelector('.post-title');
const excerpt = document.querySelector('.post-excerpt');

function isColorApplied(element) {
  const color = getComputedStyle(element).getPropertyValue('color');
  return color && color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent'; 
}

function isMarginApplied(element) {
  const margin = getComputedStyle(element).getPropertyValue('margin');
  return margin && margin !== '0px'; 
}

assert.isTrue(isColorApplied(title));
assert.isTrue(isMarginApplied(title));

assert.isTrue(isColorApplied(excerpt));
assert.isTrue(isMarginApplied(excerpt));

const styles = new __helpers.CSSHelp(document);
// Are CSS selectors used to style the elements:
const postTitle = [".post-title", ".post-excerpt, .post-title", ".post-title, .post-excerpt"].some(selector => {
  return !!styles.getStyle(selector)?.getPropVal('color');
});
const postExcerpt = [".post-excerpt", ".post-excerpt, .post-title", ".post-title, .post-excerpt"].some(selector => {
  return !!styles.getStyle(selector)?.getPropVal('color');
});
assert.isTrue(postTitle);
assert.isTrue(postExcerpt);
```

# --seed--

## --seed-contents--

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog Post Card</title>
</head>
<body>

</body>
</html>
```

```css

```

# --solutions--

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog Post Card</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="blog-post-card">
        <img src="https://cdn.freecodecamp.org/curriculum/labs/cover-photo.jpg" alt="Blog Post Image" class="post-img">
        <div class="post-content">
            <h2 class="post-title">Learn Web Development in 2024</h2>
            <p class="post-excerpt">Stay ahead of the curve with the latest trends in web development. Discover what's new and exciting in 2024</p>
            <a href="#" class="read-more">Read More</a>
        </div>
    </div>
</body>
</html>
```

```css
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
    font-family: Arial, sans-serif;
}

.blog-post-card {
    background-color: white;
    border-radius: 15px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    width: 350px;
    margin: 20px;
    text-align: center;
}

.post-img {
    width: 100%;
    height: auto;
    border-bottom: 5px solid #333;
}

.post-content {
    padding: 20px;
}

.post-title {
    color: #333;
    margin: 0 0 10px;
}

.post-excerpt {
    color: #667;
    margin: 10px 0;
}

.read-more {
    display: inline-block;
    margin-top: 10px;
    padding: 10px 15px;
    background-color: #333;
    color: white;
    text-decoration: none;
    border-radius: 5px;
}

.read-more:hover {
    background-color: #555;
}
```
