curriculum/challenges/english/blocks/lab-blog-post-card/66eaddd04a9e533fba689001.md
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:
div element with a class of blog-post-card to hold all of your card elements..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.div with a class of post-content within the .blog-post-card element with the following:
h2 element with a class of post-title and text for the title of your blog post.p element with a class of post-excerpt and text to summarize your blog post.a element with a class of read-more with the text Read More.body element's background color to a value other than white..blog-post-card element:
.post-img element should be styled so that the image fills the card's entire width and has a bottom border..post-content element should be styled so that there is padding inside the card..post-title and .post-excerpt elements should have a text color other than the default and margins on all sides..read-more element should be styled like a button and have:
display property set to inline-block.Note: Be sure to link your stylesheet in your HTML and apply your CSS.
You should have a div with a class of blog-post-card.
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.
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.
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.
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.
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.
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.
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).
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.
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);
Your body element should have a background color other than white.
const bodyBg = getComputedStyle(document.body).backgroundColor;
const whiteColors = ['rgb(255, 255, 255)', 'rgba(255, 255, 255, 1)', '#ffffff', '#fff', 'white'];
assert.isFalse(whiteColors.includes(bodyBg.toLowerCase()));
You should target .blog-post-card and set its width property.
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".blog-post-card")?.getPropertyValue("width"));
You should target .blog-post-card and set its text-align property.
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".blog-post-card")?.getPropertyValue("text-align"));
You should target .post-content and set its padding property.
assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle(".post-content")?.getPropertyValue("padding"));
Your .read-more element should have a hover effect.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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);
<!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>
<!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">
<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>
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;
}