In this exercise, we want a newsletter sign up that is layed out differently based on the container that it is in.
We repeat it, once in the main content and one in the sidebar.
Update this so that the newsletter form is on one line when it it in the main content, and stacked when it is in the sidebar.
<div class="main-content">
<newsletter-signup />
</div>
<div class="sidebar">
<newsletter-signup />
</div>
<style>
.main-content, .sidebar {
/* */
}
.newsletter__form {
display: flex;
gap: 0.5rem;
}
/* for the demo */
.main-content, .sidebar {
background-color: #eee;
max-width: 60em;
padding: 1em;
margin-bottom: 1em;
}
.main-content {
&::before {
content: 'Main content'
}
}
.sidebar {
max-width: 25em;
&::before {
content: 'Sidebar'
}
}
.newsletter {
background-color: #fff;
max-width: 560px;
margin: 3rem auto;
padding: 2rem;
border: 1px solid #d5d5d5;
border-radius: 1rem;
font-family: system-ui, sans-serif;
text-align: center;
}
.newsletter__form {
max-width: 440px;
margin: 0 auto;
}
.newsletter__form input {
min-width: 0;
flex: 1;
padding: 0.8rem 1rem;
border: 1px solid #aaa;
border-radius: 0.5rem;
font: inherit;
}
.newsletter__form button {
padding: 0.8rem 1.1rem;
border: 0;
border-radius: 0.5rem;
color: white;
background: #222;
font-weight: 700;
cursor: pointer;
}
.newsletter__fine-print {
margin: 1rem 0 0;
color: #777;
font-size: 0.8rem;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<script>
class NewsletterSignup extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<section class="newsletter">
<form class="newsletter__form">
<label class="sr-only" for="email">
Email address
</label>
<input
id="email"
name="email"
type="email"
placeholder="you@example.com"
autocomplete="email"
required
/>
<button type="submit">Subscribe</button>
</form>
<p class="newsletter__fine-print">
You can unsubscribe at any time.
</p>
</section>
`;
}
}
customElements.define("newsletter-signup", NewsletterSignup);
</script>
This is how you could do it:
container-type on each container this should work on (.main-content, .sidebar), use inline-size as we want it to respond to inline size@container query that triggers at max-width: 25em and flips the flex-direction to column.
<div class="main-content">
<newsletter-signup />
</div>
<div class="sidebar">
<newsletter-signup />
</div>
<style>
.main-content, .sidebar {
container-type: inline-size;
}
.newsletter__form {
display: flex;
gap: 0.5rem;
@container (max-width: 25em) {
flex-direction: column;
}
}
/* for the demo */
.main-content, .sidebar {
background-color: #eee;
max-width: 60em;
padding: 1em;
margin-bottom: 1em;
}
.main-content {
&::before {
content: 'Main content'
}
}
.sidebar {
max-width: 25em;
&::before {
content: 'Sidebar'
}
}
.newsletter {
background-color: #fff;
max-width: 560px;
margin: 3rem auto;
padding: 2rem;
border: 1px solid #d5d5d5;
border-radius: 1rem;
font-family: system-ui, sans-serif;
text-align: center;
}
.newsletter__form {
max-width: 440px;
margin: 0 auto;
}
.newsletter__form input {
min-width: 0;
flex: 1;
padding: 0.8rem 1rem;
border: 1px solid #aaa;
border-radius: 0.5rem;
font: inherit;
}
.newsletter__form button {
padding: 0.8rem 1.1rem;
border: 0;
border-radius: 0.5rem;
color: white;
background: #222;
font-weight: 700;
cursor: pointer;
}
.newsletter__fine-print {
margin: 1rem 0 0;
color: #777;
font-size: 0.8rem;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<script>
class NewsletterSignup extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<section class="newsletter">
<form class="newsletter__form">
<label class="sr-only" for="email">
Email address
</label>
<input
id="email"
name="email"
type="email"
placeholder="you@example.com"
autocomplete="email"
required
/>
<button type="submit">Subscribe</button>
</form>
<p class="newsletter__fine-print">
You can unsubscribe at any time.
</p>
</section>
`;
}
}
customElements.define("newsletter-signup", NewsletterSignup);
</script>