All examples

Building blocks > Container queries
Two styles of newsletter signup

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.

Example code

							<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>
						

Preview

Answer

Show the answer

This is how you could do it:

  1. Set container-type on each container this should work on (.main-content, .sidebar), use inline-size as we want it to respond to inline size
  2. Add a @container query that triggers at max-width: 25em and flips the flex-direction to column.

Example code

							<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>
						

Preview

Browser support