<layout-container data-size="small" data-bg-color="brand">
<component-card
data-title="This is a card component"
data-image="https://assets.codepen.io/437758/internal/avatars/users/default.png"
data-image-alt="Mark Conroy's avatar from CodePen.io"
data-description="We are reading a tutorial about how to create web components. More specifically, how to create nested web components."
data-cta-href="https://blog.logrocket.com/"
data-cta-text="Read more"
>
</component-card>
<component-card
data-title="This is a card component"
data-image="https://assets.codepen.io/437758/internal/avatars/users/default.png"
data-image-alt="Mark Conroy's avatar from CodePen.io"
data-description="We are reading a tutorial about how to create web components. More specifically, how to create nested web components."
data-cta-href="https://blog.logrocket.com/"
data-cta-text="Read more"
>
</component-card>
</layout-container>
class containerComponent extends HTMLElement {
constructor() {
super();
// Width
let width;
const width_small = "48em";
const width_medium = "60em";
const width_large = "80em";
// Other properties
let bgColor = "white";
const colorBrand = "pink";
const colorAccent = "lightgreen";
const colorAccentContrast = "darkgreen";
if (this.hasAttribute("data-width")) {
let widthValue = this.getAttribute("data-width");
widthValue === "small" ? width = width_small : "";
widthValue === "medium" ? width = width_medium : "";
widthValue === "large" ? width = width_large : "";
} else {
width = width_medium;
}
if (this.hasAttribute("data-bg-color")) {
let bgColorValue = this.getAttribute("data-bg-color");
bgColorValue === "brand" ? bgColor = colorBrand : "";
bgColorValue === "accent" ? bgColor = colorAccent : "";
bgColorValue === "accent-contrast" ? bgColor = colorAccentContrast : "";
}
const containerTemplate = document.createElement("template");
containerTemplate.innerHTML = `
<slot></slot>
`;
const style = document.createElement("style");
style.textContent = `
:host {
display: block;
width: 100%;
max-width: ${width};
margin-left: auto;
margin-right: auto;
background-color: ${bgColor};
}
`;
const shadowRoot = this.attachShadow({ mode: "closed" });
shadowRoot.appendChild(style);
shadowRoot.appendChild(containerTemplate.content.cloneNode(true));
}
}
customElements.define("layout-container", containerComponent);
// Create a class for the element
class Card extends HTMLElement {
constructor() {
super();
this.setAttribute("role", "article");
this.classList.add("card");
// Title
const title = document.createElement("h2");
title.classList.add("card__title");
title.textContent = this.getAttribute("data-title");
// Description
const description = document.createElement("div");
description.classList.add("card__description");
description.innerHTML = this.getAttribute("data-description");
// Image
let imageWrapper;
if (this.hasAttribute("data-image")) {
const image = document.createElement("img");
image.classList.add("card__image");
image.src = this.getAttribute("data-image");
if (this.hasAttribute("data-image-alt")) {
image.alt = this.getAttribute("data-image-alt");
}
imageWrapper = document.createElement("div");
imageWrapper.classList.add("card__image-wrapper");
imageWrapper.appendChild(image);
this.appendChild(imageWrapper);
}
// CTA
let ctaContainer;
if (this.hasAttribute('data-cta-href')) {
const cta = document.createElement("a");
cta.classList.add("card__link");
cta.href = this.getAttribute("data-cta-href");
cta.textContent = this.getAttribute("data-cta-text");
ctaContainer = document.createElement("div");
ctaContainer.classList.add('card__cta');
ctaContainer.appendChild(cta);
}
const contentContainer = document.createElement("div");
contentContainer.classList.add("card__content");
contentContainer.appendChild(title);
contentContainer.appendChild(description);
if (ctaContainer !== 'undefined') {
contentContainer.appendChild(ctaContainer);
}
// Create some CSS to apply to the shadow dom
const style = document.createElement("style");
style.textContent = `
:host {
display: block;
background: #eaeaea;
border-radius: 10px;
border: 1px solid black;
max-width: 300px;
color: #333;
}
.card__content {
padding: 1rem;
}
.card__title {
color: #333;
margin-top: 0;
line-height: 1.1;
}
img {
width: 100%;
display: block;
border-radius: 10px 10px 0 0;
}
.card__cta {
margin-top: 1.5rem;
}
.card__cta a {
color: #eaeaea;
display: block;
background-color: #333;
padding: 0.25rem 1rem;
border-radius: 5px;
text-align: center;
}
`;
// Attach the created elements to the shadow dom
const shadowRoot = this.attachShadow({ mode: "closed" });
shadowRoot.appendChild(style);
if (imageWrapper !== undefined) {
shadowRoot.appendChild(imageWrapper);
}
shadowRoot.appendChild(contentContainer);
}
}
// Define the new element
customElements.define("component-card", Card);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.