<ul class="navbar">
<li class="nav-item"><a href="#">Item 1</a></li>
<li class="nav-item"><a href="#">Item 2</a></li>
<li class="nav-item"><a href="#">Item 3</a></li>
<li class="nav-item"><a href="#">Item 4</a></li>
<li class="nav-item with-dropdown">
<div class="dropdown-meta">
<span class="dropdown-label">Dropdown</span>
<span class="dropdown-icon"></span>
</div>
<div class="dropdown__wrapper">
<div class="dropdown">
<div class="dropdown-header">
<button class="dropdown-restore" title="Restore items">Restore Items</button>
<button class="dropdown-close" title="Close">Close</button>
</div>
<div class="dropdown-body">
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://icons.veryicon.com/png/o/food--drinks/vegetable-set/potato-6.png">
</div>
<div class="textbox">
<span class="product-name">Potatoes</span>
<span class="product-description">Naturally grown potatoes with rich flavor and perfect texture — straight from the field to your table.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/117962/onion.svg">
</div>
<div class="textbox">
<span class="product-name">Onions</span>
<span class="product-description">Naturally grown onions with bold flavor and firm texture — fresh from the field to your kitchen.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/53717/lettuce.svg">
</div>
<div class="textbox">
<span class="product-name">Lettuces</span>
<span class="product-description">Fresh, naturally grown lettuce with crisp texture and vibrant flavor — straight from the field to your table.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/405717/garlic.svg">
</div>
<div class="textbox">
<span class="product-name">Garlic</span>
<span class="product-description">Naturally grown garlic with rich aroma and bold taste — fresh from the field to your kitchen.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/125741/orange.svg">
</div>
<div class="textbox">
<span class="product-name">Oranges</span>
<span class="product-description">Sweet, handpicked oranges full of vibrant citrus flavor — fresh from the orchard to your hands.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/489691/tomato.svg">
</div>
<div class="textbox">
<span class="product-name">Tomatoes</span>
<span class="product-description">Sun-ripened tomatoes bursting with juicy flavor — picked fresh and ready to enhance your meals.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
<div class="dropdown-item">
<div class="product">
<div class="media">
<img src="https://www.svgrepo.com/show/486303/milk.svg">
</div>
<div class="textbox">
<span class="product-name">Milk</span>
<span class="product-description">Fresh, creamy milk from naturally raised cows — pure goodness straight to your table.</span>
<a href="#" class="product-info-btn">More info</a>
</div>
<div class="actions">
<button class="remove-button" title="Remove">Remove</button>
</div>
</div>
</div>
</button>
</div>
</button>
</li>
</ul>
// BASIC STYLES: Nothing important here. The magic comes below.
* {
box-sizing: border-box;
}
body {
position: relative;
width: 100%;
min-height: 100svh;
padding: 0;
margin: 0;
background-color: silver;
overflow: hidden;
overflow: clip;
font-family: 'System UI', sans-serif;
}
.navbar {
position: fixed;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: flex-end;
flex-wrap: nowrap;
gap: 40px;
width: 100%;
padding: 15px;
margin: 0;
border-top: 1px solid white;
border-bottom: 1px solid black;
background-color: white;
list-style-type: none;
}
.nav-item {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
> a {
display: inline-flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
gap: 10px;
padding: 10px;
border: 1px solid black;
border-radius: 4px;
text-decoration: none;
color: black;
transition: background-color 400ms, color 400ms, border-color 400ms;
&:hover,
&:active {
background-color: #660000;
color: white;
border-color: #660000;
}
}
.dropdown-meta {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: no-wrap;
gap: 10px;
padding: 10px;
border: 1px solid black;
border-radius: 4px;
cursor: pointer;
transition: color 400ms, background-color 400ms, border 400ms;
&:hover,
&:active {
background-color: #660000;
color: white;
border-color: #660000;
.dropdown-icon {
background-color: white;
}
}
}
.dropdown-icon {
display: inline-flex;
width: 16px;
height: 16px;
mask-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Feather-arrows-chevron-down.svg/1200px-Feather-arrows-chevron-down.svg.png');
mask-size: contain;
mask-position: center center;
mask-repeat: no-repeat;
background-color: black;
transition: background-color 400ms, transform 400ms;
}
&.open {
.dropdown-icon {
transform: rotate(180deg);
}
}
}
.dropdown__wrapper {
display: none;
position: absolute;
top: 100%;
right: 0;
z-index: 1;
border-right: none;
border-left: 1px solid black;
border-bottom: 1px solid black;
border-top: 1px solid white;
background-color: white;
border-radius: 0 0 0 4px;
}
.dropdown-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 15px;
border-bottom: 1px solid silver;
margin-bottom: 15px;
}
.dropdown-restore,
.dropdown-close {
position: relative;
appearance: none;
width: 15px;
height: 15px;
padding: 0;
border: none;
color: transparent;
background-color: transparent;
text-indent: -100vw;
font-size: 0;
line-height: 0;
cursor: pointer;
&:after {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
mask-position: center center;
mask-size: contain;
mask-repeat: no-repeat;
}
}
.dropdown-restore {
&:after {
mask-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Refresh_icon.svg/768px-Refresh_icon.svg.png');
}
}
.dropdown-close {
&:after {
mask-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Grey_close_x.svg/768px-Grey_close_x.svg.png');
}
}
.product {
position: relative;
display: grid;
grid-template-columns: minmax(0, 80px) minmax(0, 1fr) minmax(0, 30px);
gap: 15px;
overflow: hidden;
overflow: clip;
.media {
img {
width: 100%;
height: auto;
aspect-ratio: 1/1;
object-fit: contain;
object-position: center center;
}
}
.textbox {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: 10px;
color: black;
}
.product-name {
font-size: 1.2rem;
font-weight: bold;
}
.product-description {
font-style: italic;
text-wrap: balance;
}
.product-info-btn {
padding: 5px 10px;
border: 1px solid black;
font-size: 0.8rem;
text-decoration: none;
color: black;
transition: color 400ms, background-color 400ms, border 400ms;
border-radius: 4px;
pointer-events: auto;
&:visited {
color: black;
}
&:hover,
&:active {
background-color: #660000;
color: white;
border-color: #660000;
}
}
.actions {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
}
.remove-button {
position: relative;
appearance: none;
width: 30px;
height: 30px;
padding: 0;
border: none;
color: transparent;
background-color: transparent;
text-indent: -100vw;
font-size: 0;
line-height: 0;
cursor: pointer;
&:after {
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
mask-image: url('https://upload.wikimedia.org/wikipedia/commons/9/93/Trash_can.svg');
mask-position: center center;
mask-size: contain;
mask-repeat: no-repeat;
}
}
}
// HERE COMES THE MAGIC.
.dropdown {
display: flex;
flex-direction: column;
// Our dropdown is limited in size by the designs.
width: 500px;
// Total window height less navbar height.
max-height: calc(100svh - 72px);
padding: 30px;
overflow: hidden;
container-type: inline-size;
container-name: dropdown;
}
.dropdown-body {
display: flex;
flex-direction: column;
gap: 30px;
// Adding the scrollbar if needed.
overflow-y: auto;
// Full container + 24px for the placing the scrollbar and an inner space and not be just at the edge. This would keep the space for the scrollbar independently if there is one item or more without missalignments.
width: calc(100cqw + 24px);
}
.dropdown-item {
max-width: 100cqw;
}
View Compiled
// This JS code is only for adding the nabvar behaviors. Nothing related to the pure CSS solution.
const $navbar = $('.navbar');
const $dropdownEl = $navbar.find('.nav-item.with-dropdown');
const $closeDropdownBtn = $dropdownEl.find('.dropdown-close');
const originalContents = [];
// Function to attach remove event handler using delegation-friendly approach.
const reAttachRemove = function(element) {
// Remove any previous click handlers and add a new one
element.off('click').on('click', function(e) {
e.stopPropagation();
$(this).closest('.dropdown-item').remove();
});
}
// Initialize each dropdown.
$dropdownEl.each(function(index) {
const $this = $(this);
const $restoreBtn = $this.find('.dropdown-restore');
// Save original content of dropdown-body to restore later.
originalContents[index] = $this.find('.dropdown-body').children().clone();
// Initially attach remove handlers to existing remove buttons.
$this.find('.remove-button').each(function() {
reAttachRemove($(this));
});
// Restore original content when clicking restore button.
$restoreBtn.on('click', function(e) {
e.stopPropagation();
const $dropdownBody = $(this).closest('.dropdown').find('.dropdown-body');
$dropdownBody.empty();
// Clone with events true to preserve original bindings if any (better safe than sorry).
const restoredContent = originalContents[index].clone(true, true);
$dropdownBody.append(restoredContent);
// Reattach remove handlers to the newly added remove buttons.
$dropdownBody.find('.remove-button').each(function() {
reAttachRemove($(this));
});
});
});
// Toggle dropdown open/close on click.
$dropdownEl.on('click', function(e) {
e.stopPropagation();
const $this = $(this);
const $wrapper = $this.find('.dropdown__wrapper');
$wrapper.slideToggle();
$this.toggleClass('open');
});
// Close dropdown on clicking close button.
$closeDropdownBtn.on('click', function(e) {
e.stopPropagation();
const $wrapper = $(this).closest('.dropdown__wrapper');
const $parentDropdown = $(this).closest('.nav-item.with-dropdown');
$wrapper.slideUp();
$parentDropdown.removeClass('open');
});
// Delegate remove-button clicks on navbar container (ensures it works for dynamic elements too).
$navbar.on('click', '.remove-button', function(e) {
e.stopPropagation();
$(this).closest('.dropdown-item').remove();
});
// Close all dropdowns if clicking outside any dropdown element.
$(document).on('click', function(e) {
if ($(e.target).closest('.nav-item.with-dropdown').length === 0) {
$dropdownEl.find('.dropdown__wrapper').slideUp();
$dropdownEl.removeClass('open');
}
});
This Pen doesn't use any external CSS resources.