Skip to main content

Command Palette

Search for a command to run...

The dialog element: The way to create tomorrow’s modal windows - LogRocket Blog

Updated
19 min read
The dialog element: The way to create tomorrow’s modal windows - LogRocket Blog

[

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →

](https://lp.logrocket.com/blg/content-advisory-board-signup).metrics-banner {padding: 8px 0px; background: #764abc ;color: #ffffff;} .metrics-banner h6 {color: #ffffff;text-align:center; margin: 0px !important;} #metrics-embed {width: 65.5%; margin: 0px auto; display: block;} .mediumnavigation {padding: 0px 0px 8px 0px;} @media all and (max-width: 800px){ .mediumnavigation{box-shadow: none !important;} #metrics-embed {width: 90%;} .mainheading {padding: 4rem 0 1rem 0;} }

LogRocket blog logo

2019-04-17

1753

#html

Abishek Jakhar

242

Apr 17, 2019 ⋅ 6 min read

The dialog element: The way to create tomorrow’s modal windows

Abishek Jakhar Designer, Developer & Gamer

LogRocket Galileo logo

Introducing Galileo AI

LogRocket’s Galileo AI watches every session, surfacing impactful user struggle and key behavior patterns.

LEARN MORE

const threshold = 2000; const isMobile = window.matchMedia("(max-width: 1280px)").matches; window.addEventListener('scroll', (event) => { if (isMobile) { return; } const gutter = document.querySelector(".plug-gutter"); // show it if it is hidden and we have scrolled past the threshold if (window.scrollY > threshold && !gutter.classList.contains("show")) { gutter.classList.add("show"); window.toggleToc(true); } // hide it if we scroll back above the threshold if (window.scrollY < threshold && gutter.classList.contains("show")) { gutter.classList.remove("show"); window.toggleToc(false); } });

.plug-dev-top--card { border: 2px solid rgba(118, 74, 188, 0.2); border-radius: 8px; background-color: #491d90; justify-content: space-between; align-items: center; padding: 16px; font-family: 'Proxima Nova', sans-serif; display:flex; gap: 1rem; cursor: pointer; } .plug-dev-top--logo { width: 48px; height: 48px; border-radius: 50%; } .plug-dev-top--blurb { h2 { font-weight: 800; font-size: 22px; line-height: 22px; color: #fff; width: 70%; margin: 0 0 5px 0; } h3 { font-weight: 900; font-size: 13px; line-height: 13px; letter-spacing: 0.1em; color: #fff; opacity: 0.5; white-space: nowrap; margin: 0; } } .plug-dev-top--cta { background-color: #fff; color: #764abc; border: none; border-radius: 4px; padding: 10px; font-size: 16px; font-weight: 800; font-family: 'Proxima Nova', sans-serif; text-decoration: none; width: 25%; text-align: center; &:hover { text-decoration: none; color: #a58ec8; } } .plug-dev-top--asset { position: relative; height: 400px; overflow: hidden; transition: all 0.3s ease; margin-top: 30px; &.lr-hidden { height: 0; margin: 0; } }

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

const wistiaIframe = document.querySelector("#galileo-wistia-iframe"); wistiaIframe.addEventListener('load', () => { const player = wistiaIframe.wistiaApi; window.document.querySelector(".plug-dev-top").addEventListener('click', () => { const videoContainer = window.document.querySelector(".plug-dev-top--asset"); videoContainer.classList.toggle('lr-hidden'); if (videoContainer.classList.contains("lr-hidden")) { player.pause(); } else { player.play(); } }); });

Overview

The dialog box is a common user interface design pattern that comes up over and over again on websites — so often that the W3C came up with some standardized HTML markup to describe a dialog window.

Using The Dialog Element For Modal Windows

Traditional dialog windows created with other HTML markup and CSS have been implemented in most front-end frameworks for a long time, and that’s probably still the way to go since the HTML dialog element still has limited browser support.

But if front-end frameworks are still the better choice, why create a standardized dialog element?

Well, there are many reasons, but chief among them is accessibility by screen readers and enabling things like search engine crawlers and machine learning agents to interpret the dialog window. As browser support improves over time, this standard will be the clear choice to create modal windows moving forward.

First, we’ll focus on the HTML markup for the dialog element, then we’ll add some JavaScript later.

The folder structure might look like this:

project
| —
index.html | —app.js | —main.css

The HTML behind our dialog window

Inside the index.html file, let’s create the dialog element with an opening and closing tag:

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
  </head>
  <body>
    <dialog>
    </dialog>
  </body>
  http://app.js
</html>

Creating a element.

However, this won’t show anything on the page just yet. In order for this to appear, we need to add the boolean attribute open to the dialog element:

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
  </head>
  <body>
    <dialog open>
    </dialog>
  </body>
  http://app.js
</html>

Adding boolean attribute open to the element to make it appear on the page.

Inside the dialog element, we’ll create a simple form with a text input of type text and a button of type submit:

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
  </head>
  <body>
    <dialog open>
      <form method="dialog">
        <input type="text">
        <button type="submit">SUBMIT</button>
      </form>
    </dialog>
  </body>
  http://app.js
</html>

Note: Here I’ve set a method of the form to dialog. This is a new form method that works in coordination with the parent dialog element. When the submit button is pressed, it will submit the form and dismiss the dialog window.

Dialog window disappearing after pressing the submit button.

Now we’ll create some buttons that will allow us to make the dialog window reappear. These will need JavaScript to work, which we will add later.

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
  </head>
  <body>
    <dialog open>
      <form method="dialog">
        <input type="text">
        <button type="submit">OK</button>
      </form>
    </dialog>

    <button id="openDialog">Dialog</button>
    <button id="openModalDialog">Modal Dialog</button>
  </body>
  http://app.js
</html>

Added two buttons with the IDs “openDialog” and “openModalDialog”.

So, here we have created two buttons: one with the ID openDialog, and another with the ID openModalDialog. Once we add some JavaScript, the first button will open the dialog window just like we saw above. However, the second button will open a dialog window that blocks other page interactions.

This is a common design pattern because when a dialog window is open, you often need the user to perform some sort of interaction before they continue using the rest of the application.

For writing the JavaScript, I will remove the open attribute from the dialog element and then add an ID attribute so we can select it with our JavaScript, just like the buttons.

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
  </head>
  <body>
    <dialog id="dialogWindow">
      <form method="dialog">
        <input type="text">
        <button type="submit">OK</button>
      </form>
    </dialog>

    <button id="openDialog">Open Dialog</button>
    <button id="openModalDialog">Open Modal Dialog</button>
  </body>
  http://app.js
</html>

Replaced open attribute of element with the ID of name “dialogWindow”.

The JavaScript for our dialog window

Inside the JavaScript (app.js) file, we will write our event-based code in an anonymous function, which will be executed on page load.


[

](https://lp.logrocket.com/blg/learn-more)

[#replay-signup { margin-block: 1rem; display: flex; gap: 0.5rem; flex-direction: column; align-items: center; border: 1px solid #E6DFF6; border-radius: 16px; padding: 0.5rem 2rem; background-color: #F4F0FB; font-family: 'Proxima Nova', sans-serif; font-size: 0.95rem; h3 { margin: 0; font-weight: bold; } p { max-inline-size: 65ch; } .replay-signup-form-wrapper { width: 60%; } .nf-before-form-content { display: none; } input.nf-element[type="submit"] { background-color: #764abc; color: #fff; border-radius: 8px; padding-block: 10px; height: unset; width: 100%; display: block; } .nf-response-msg { font-size: 1.2rem; text-align: center; } }

🚀 Sign up for The Replay newsletter

](https://lp.logrocket.com/blg/learn-more)

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

Notice: JavaScript is required for this content.

var formDisplay=1;var nfForms=nfForms||[];var form=[];form.id='48';form.settings={"objectType":"Form Setting","editActive":true,"title":"Replay Newsletter Signup","show_title":0,"allow_public_link":0,"embed_form":"","clear_complete":1,"hide_complete":1,"default_label_pos":"above","wrapper_class":"","element_class":"","form_title_heading_level":"3","key":"","add_submit":0,"changeEmailErrorMsg":"Please enter a valid email address!","changeDateErrorMsg":"Please enter a valid date!","confirmFieldErrorMsg":"These fields must match!","fieldNumberNumMinError":"Number Min Error","fieldNumberNumMaxError":"Number Max Error","fieldNumberIncrementBy":"Please increment by ","formErrorsCorrectErrors":"Please correct errors before submitting this form.","validateRequiredField":"This is a required field.","honeypotHoneypotError":"Honeypot Error","fieldsMarkedRequired":"Fields marked with an *<\/span> are required","currency":"","unique_field_error":"A form with this value has already been submitted.","logged_in":false,"not_logged_in_msg":"","sub_limit_msg":"The form has reached its submission limit.","calculations":[],"conditions":[],"mp_breadcrumb":1,"mp_progress_bar":1,"mp_display_titles":0,"formContentData":[{"formContentData":["email","submit_1760469924554"],"order":0,"type":"part","clean":true,"title":"Part Title","key":"hzyqqobd"}],"objectDomain":"display","drawerDisabled":false,"ninjaForms":"Ninja Forms","fieldTextareaRTEInsertLink":"Insert Link","fieldTextareaRTEInsertMedia":"Insert Media","fieldTextareaRTESelectAFile":"Select a file","formHoneypot":"If you are a human seeing this field, please leave it empty.","fileUploadOldCodeFileUploadInProgress":"File Upload in Progress.","fileUploadOldCodeFileUpload":"FILE UPLOAD","currencySymbol":"$","thousands_sep":",","decimal_point":".","siteLocale":"en_US","dateFormat":"m\/d\/Y","startOfWeek":"1","of":"of","previousMonth":"Previous Month","nextMonth":"Next Month","months":["January","February","March","April","May","June","July","August","September","October","November","December"],"monthsShort":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"weekdays":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"weekdaysShort":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"weekdaysMin":["Su","Mo","Tu","We","Th","Fr","Sa"],"recaptchaConsentMissing":"reCaptcha validation couldn't load.","recaptchaMissingCookie":"reCaptcha v3 validation couldn't load the cookie needed to submit the form.","recaptchaConsentEvent":"Accept reCaptcha cookies before sending the form.","currency_symbol":"","beforeForm":"","beforeFields":"","afterFields":"","afterForm":""};form.fields=[{"objectType":"Field","objectDomain":"fields","editActive":false,"order":999,"idAttribute":"id","type":"email","label":"Email","key":"email","label_pos":"hidden","required":1,"default":"","placeholder":"Email","container_class":"","element_class":"","admin_label":"","help_text":"","custom_name_attribute":"email","personally_identifiable":1,"value":"","manual_key":true,"drawerDisabled":false,"id":401,"beforeField":"","afterField":"","parentType":"email","element_templates":["email","input"],"old_classname":"","wrap_template":"wrap"},{"objectType":"Field","objectDomain":"fields","editActive":false,"order":999,"idAttribute":"id","type":"submit","label":"Submit","processing_label":"Submitting...","container_class":"","element_class":"","key":"submit_1760469924554","admin_label":"","drawerDisabled":false,"id":402,"beforeField":"","afterField":"","value":"","label_pos":"above","parentType":"textbox","element_templates":["submit","button","input"],"old_classname":"","wrap_template":"wrap-no-label"}];nfForms.push(form);

{{{ data.renderProgressBar() }}} {{{ data.renderBreadcrumbs() }}} {{{ data.renderPartTitle() }}}

{{{ data.title }}}

{{{ data.renderNextPrevious() }}}
    <# if ( data.showPrevious ) { #>
  • <# } #> <# if ( data.showNext ) { #>
  • <# } #>

function registerNinjaFormsCallback() { if (!(window.nfRadio && window.lr_analytics)) { return; } window.nfRadio.channel("forms").on("submit:response", function(submission) { console.log(submission); if (submission.data.form_id !== "48") { return; } window.lr_analytics.track("blog-replay-newsletter-signup", { post: window.location.pathname, email: submission.data.fields_by_key?.email?.value, }); }); } registerNinjaFormsCallback();

Over 200k developers use LogRocket to create better digital experiences

Learn more →


@media all and (max-width: 800px){ .tweet-embed-container {flex-direction: column !important;} .single-tweet, .embed-tweet-right {width: 100% !important;} } .embed-link {text-decoration: none;} .embed-link:hover {text-decoration: none;} .tweet-embed-container {border-radius: 20px; background: radial-gradient(79.69% 102.24% at 100% 100.11%, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), radial-gradient(89.7% 115.09% at 3.43% 2.75%, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0)), #764ABC; background-blend-mode: overlay, overlay, normal; box-shadow: 0 4px 0 #d5d5d5; width: auto; padding: 20px 15px; display: flex; flex-direction: row; justify-content: space-evenly; align-items: center; margin: 0 auto; gap: 3%; } .single-tweet {width: 50%;} .single-tweet img {max-width: 100%;height: auto; border-radius:7px;} .embed-tweet-right {width: 46%;} .embed-tweet-right h2 {font-family: 'Avenir'; font-style: normal; font-weight: 500; font-size: 16px; line-height: 28px; color: #FFFFFF;} .embed-btn { display: flex; flex-direction: row; justify-content: left; width: 170px; gap: 5px; align-items: center; padding: 0px 10px; font-family: 'Avenir'; font-style: normal; font-weight: 900; font-size: 16px; line-height: 16px; color: #764ABC; height: 48px; /* White */ background: #FFFFFF; mix-blend-mode: normal; box-shadow: 0px 24px 30px rgba(0, 0, 0, 0.11); border-radius: 80px; border: none; }

First, we will gather the elements on the page, along with the variables — the dialog window and the two buttons. We’ll create a variable for each and get them by their ID.

(function() {

  let openDialog = document.getElementById('openDialog');
  let openModalDialog = document.getElementById('openModalDialog');
  let dialogWindow = document.getElementById('dialogWindow');

})();

Getting the two buttons and dialog window by their IDs.

Next, we will create two event listeners, one for each button.

1. EventListener for opening the dialog window normally

We will add an EventListener to the openDialog button so that when it’s clicked, the function show() will execute. The show() function displays the dialog element on the page the same way it did when we used the open attribute earlier in our HTML.

(function() {

  let openDialog = document.getElementById('openDialog');
  let openModalDialog = document.getElementById('openModalDialog');
  let dialogWindow = document.getElementById('dialogWindow');

  openDialog.addEventListener('click', () => {
    dialogWindow.show();
  })

})();

EventListener for opening the dialog window normally.

EventListener for opening the dialog window normally.

Note: I have styled the buttons so that they are visible on the GIF above, but it won’t affect functionality in any way.

2. EventListener for opening the dialog window as a modal window

We’re going to do the same thing for our open modal window dialog as we did above: add an EventListener to the openModalDialog button so that when it’s clicked, the function showModal() will execute.

So here, instead of the show() function, we’re using the showModal() function, which will still show the dialog window. But this time, the rest of the page will have a gray, transparent overlay that will block any other mouse clicks.

(function() {

  let openDialog = document.getElementById('openDialog');
  let openModalDialog = document.getElementById('openModalDialog');
  let dialogWindow = document.getElementById('dialogWindow');

  openDialog.addEventListener('click', () => {
    dialogWindow.show();
  })

  openModalDialog.addEventListener('click', () => {
    dialogWindow.showModal();
  })
})();

EventListener for opening the dialog window as a modal window.

Dialog window as a modal window.

Browser support and polyfill

A polyfill is a piece of code that implements a feature that isn’t natively supported by particular web browsers. Typically, they first check whether a browser supports an API and use that if available; otherwise, they implement their logic to make it work on the browser.

Right now, only Chrome and Opera fully support the HTML dialog element, and in order to use it in Firefox, the user must explicitly enable the feature.

But we can still use the HTML dialog element in other browsers(Safari, IE, etc.) using dialog-polyfill, which is maintained by Google Chrome. The polyfill will add support for non-supporting browsers; it also supports IE9 and above.


More great articles from LogRocket:


A couple things to note: adding polyfill in our JavaScript (app.js) file won’t affect the HTML dialog element working on Chrome and Opera in any way. There will only be the single app.js file.

Additionally, if we want to use the HTML dialog element only on Chrome or Opera, we won’t need a polyfill. But if we want to use it on all browsers — which would probably be the case — we will have to use polyfill until there is complete support on the rest of the browsers.

The updated folder structure might look like this:

project
| —
index.html | —app.js | —main.css | —dialog-polyfill.css | —dialog-polyfill.js

Using polyfill

  1. Include the CSS [dialog-polyfill.css](https://github.com/GoogleChrome/dialog-polyfill/blob/master/dist/dialog-polyfill.css) in the head of your document.
<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
    <link rel="stylesheet" href="dialog-polyfill.css">
    <link rel="stylesheet" href="main.css">
  </head>
  <body>
    <dialog id="dialogWindow">
      <form method="dialog">
        <input type="text">
        <button type="submit">OK</button>
      </form>
    </dialog>

    <button id="openDialog" class="button">Open Dialog</button>
    <button id="openModalDialog" class="button">Open Modal Dialog</button>
  </body>
  http://app.js
</html>

Included dialog-polyfill.css.

2. Include the JavaScript [dialog-polyfill.js](https://github.com/GoogleChrome/dialog-polyfill/blob/master/dist/dialog-polyfill.js) anywhere before referencing dialogPolyfill.

<!doctype html>
<html>
  <head>
    <title>HTML Dialog Element</title>
    <link rel="stylesheet" href="dialog-polyfill.css">
    <link rel="stylesheet" href="main.css">
  </head>
  <body>
    <dialog id="dialogWindow">
      <form method="dialog">
        <input type="text">
        <button type="submit">OK</button>
      </form>
    </dialog>

    <button id="openDialog" class="button">Open Dialog</button>
    <button id="openModalDialog" class="button">Open Modal Dialog</button>
  </body>
  http://dialog-polyfill.js
  http://app.js
</html>

Included dialog-polyfill.js

3. Create the <dialog> element within the HTML document (we have already created one above).

  1. Register the elements using the dialogPolyfill.registerDialog() function, passing it one node at a time.
(function() {

    let openDialog = document.getElementById('openDialog');
    let openModalDialog = document.getElementById('openModalDialog');
    let dialogWindow = document.getElementById('dialogWindow');

    dialogPolyfill.registerDialog(dialogWindow);

    openDialog.addEventListener('click', () => {
      dialogWindow.show();
    })

    openModalDialog.addEventListener('click', () => {
      dialogWindow.showModal();
    })
  })();

Registered dialog polyfill using dialogPolyfill.registerDialog() function in app.js.

5. Use your <dialog> element.

Safari browser before adding polyfill (left) vs. after adding polyfill (right).

Now we have covered the essentials of the dialog element in HTML. If you’re interested in learning more, consider reading these resources from Mozilla and Can I use…, as well as the official spec.

I hope you’ve found this post informative and helpful. I would love to hear your feedback!

Thank you for reading!

.plug-cta-button { display: block; margin: 0 auto; width: 250px; height: 55px; background-color: #764abc; border-radius: 8px; color: #fff !important; font-family: proxima-nova, sans-serif; font-size: 16px; font-weight: 800; text-decoration: none; text-align: center; line-height: 55px } #plug-tabs > ul { display: flex; border-bottom: 1px solid gray; list-style: none; padding: 0; } #plug-tabs > ul li a, #plug-tabs > ul li a:active, #plug-tabs > ul li a:hover { display: block; padding: 0.25rem 1rem; text-decoration: none; } #plug-tabs .ui-tabs-active { border-top-right-radius: 8px; border-top-left-radius: 8px; border: 1px solid gray; border-bottom: 1px solid white; margin-bottom: -1px; } #plug-tabs pre { margin: 0 0 1rem 0; } window.addEventListener('load', function() { jQuery("#plug-tabs").tabs(); });

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket

    // Code:

    import LogRocket from 'logrocket'; LogRocket.init('app/id');

// Add to your HTML:

  1. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin

Get started now

.share-icon.share-twitter span:first-child { background-image: url("https://blog.logrocket.com/wp-content/themes/logrocket/assets/svgs/share-twitter.svg"); } .share-icon.share-reddit span:first-child { background-image: url("https://blog.logrocket.com/wp-content/themes/logrocket/assets/svgs/share-reddit.svg"); } .share-icon.share-linkedin span:first-child { background-image: url("https://blog.logrocket.com/wp-content/themes/logrocket/assets/svgs/share-linkedin.svg"); } .share-icon.share-facebook span:first-child { background-image: url("https://blog.logrocket.com/wp-content/themes/logrocket/assets/svgs/share-facebook.svg"); }

Stop guessing about your digital experience with LogRocket

[

Get started for free

](https://lp.logrocket.com/blg/signup)

@media all and (max-width: 750px) { .footer-cta-logo-container {display:none !important;} .footer-cta-container h2 {width: 90% !important; padding-top: 50px !important;} .footer-cta-button {width: 40% !important;} } .footer-cta-container {border-radius: 20px;background: linear-gradient(90.32deg, #8F00FF 0.28%, rgba(143, 0, 255, 0) 99.72%), #764ABC; box-shadow: 0px 64px 74px 0px #764ABC40; padding-bottom: 30px; width: 95%; margin: 0 auto 60px auto; position: relative; margin-top: 3rem; } .footer-cta-tr {position: absolute; top: 30px; right: 30px; } .footer-cta-bl {position: absolute; bottom: 30px; left: 30px; } .footer-cta-bl {} .footer-cta-logo-container { width: 20%; padding: 10px 15px; display:block; margin: 0 auto; position: relative; background: #fafafa; border-radius: 0 0 20px 20px; } .footer-cta-logo-container::before { content: ""; position: absolute; top: 0px; height: 50px; left: -25px; width: 25px; border-top-right-radius: 25px; box-shadow: 0 -25px 0 0 #fafafa; } .footer-cta-logo-container::after { content: ""; position: absolute; top: 0px; height: 50px; right: -25px; width: 25px; border-top-left-radius: 25px; box-shadow: 0 -25px 0 0 #fafafa; } .footer-cta-container h2 {color: #ffffff; text-align: center; width: 70%; position: relative; margin: 40px auto;} .footer-cta-container a {text-decoration: none;} .footer-cta-logo-container img {display: block; margin: 0 auto; padding: 10px; max-width: 150px;} .footer-cta-br {position: absolute; left: 5px; bottom: 5px;} .footer-cta-button {padding: 10px 20px; border: 1px solid #ffffff; width: 20%; border-radius: 20px; color: #ffffff; position: relative; display:block; margin: 0 auto 20px auto; text-align: center; text-decoration: none;}

Recent posts:

[

Introducing Valdi

Should you bet on Valdi instead of React Native?

](https://blog.logrocket.com/valdi-instead-react-native/)

Valdi skips the JavaScript runtime by compiling TypeScript to native views. Learn how it compares to React Native’s new architecture and when the trade-off makes sense.

Ikeh Akinyemi

Dec 30, 2025 ⋅ 7 min read

[

8 frontend development trends 2026

](https://blog.logrocket.com/8-trends-web-dev-2026/)

What trends will define web development in 2026? Check out the eight most important trends of the year, from AI-first development to TypeScript’s takeover.

David Omotayo

Dec 30, 2025 ⋅ 6 min read

[

AI First Debugging

AI-first debugging: Tools and techniques for faster root cause analysis

](https://blog.logrocket.com/ai-debugging/)

AI-first debugging augments traditional debugging with log clustering, pattern recognition, and faster root cause analysis. Learn where AI helps, where it fails, and how to use it safely in production.

Alexander Godwin

Dec 29, 2025 ⋅ 6 min read

[

Container queries in 2026: Powerful, but not a silver bullet

](https://blog.logrocket.com/container-queries-2026/)

Container queries let components respond to their own layout context instead of the viewport. This article explores how they work and where they fit alongside media queries.

Sebastian Weber

Dec 26, 2025 ⋅ 12 min read

View all posts

#comments .comment .reply::after { background-image: url("https://blog.logrocket.com/wp-content/themes/logrocket/assets/svgs/reply.svg"); background-repeat: no-repeat; }

Leave a ReplyCancel reply

document.addEventListener('DOMContentLoaded', function () { var commentForms = document.getElementsByClassName('jetpack_remote_comment'); for (var i = 0; i < commentForms.length; i++) { commentForms[i].allowTransparency = false; commentForms[i].scrolling = 'no'; } });

{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/logrocket/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}

Hey there, want to help make our blog better?

Yea No Thanks

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now

var codePrettifyLoaderBaseUrl = "https:\/\/blog.logrocket.com\/wp-content\/plugins\/code-prettify\/prettify"; //# sourceURL=code-prettify-js-before var WPGroHo = {"my_hash":""}; //# sourceURL=wpgroho-js-extra _stq = window._stq || []; _stq.push([ "view", JSON.parse("{\"v\":\"ext\",\"blog\":\"217016018\",\"post\":\"242\",\"tz\":\"-5\",\"srv\":\"blog.logrocket.com\",\"hp\":\"vip\",\"j\":\"1:15.1.1\"}") ]); _stq.push([ "clickTrackerInit", "217016018", "242" ]); //# sourceURL=jetpack-stats-js-before {"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://blog.logrocket.com/wp-includes/js/wp-emoji-release.min.js?ver=6.9"}} /*! This file is auto-generated */ const a=JSON.parse(document.getElementById("wp-emoji-settings").textContent),o=(window._wpemojiSettings=a,"wpEmojiSettingsSupports"),s=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const a=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===a[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e{s[e]=t(o,e,n,a)}),s}function r(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}a.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf(){i(n=e.data),r.terminate(),t(n)})}catch(e){}i(n=f(s,u,c,p))}t(n)}).then(e=>{for(const n in e)a.supports[n]=e[n],a.supports.everything=a.supports.everything&&a.supports[n],"flag"!==n&&(a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&a.supports[n]);var t;a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&!a.supports.flag,a.supports.everything||((t=a.source||{}).concatemoji?r(t.concatemoji):t.wpemoji&&t.twemoji&&(r(t.twemoji),r(t.wpemoji)))}); //# sourceURL=https://blog.logrocket.com/wp-includes/js/wp-emoji-loader.min.js (function () { const iframe = document.getElementById( 'jetpack_remote_comment' ); const watchReply = function() { // Check addComment._Jetpack_moveForm to make sure we don't monkey-patch twice. if ( 'undefined' !== typeof addComment && ! addComment._Jetpack_moveForm ) { // Cache the Core function. addComment._Jetpack_moveForm = addComment.moveForm; const commentParent = document.getElementById( 'comment_parent' ); const cancel = document.getElementById( 'cancel-comment-reply-link' ); function tellFrameNewParent ( commentParentValue ) { const url = new URL( iframe.src ); if ( commentParentValue ) { url.searchParams.set( 'replytocom', commentParentValue ) } else { url.searchParams.delete( 'replytocom' ); } if( iframe.src !== url.href ) { iframe.src = url.href; } }; cancel.addEventListener( 'click', function () { tellFrameNewParent( false ); } ); addComment.moveForm = function ( _, parentId ) { tellFrameNewParent( parentId ); return addComment._Jetpack_moveForm.apply( null, arguments ); }; } } document.addEventListener( 'DOMContentLoaded', watchReply ); // In WP 6.4+, the script is loaded asynchronously, so we need to wait for it to load before we monkey-patch the functions it introduces. document.querySelector('#comment-reply-js')?.addEventListener( 'load', watchReply ); const commentIframes = document.getElementsByClassName('jetpack_remote_comment'); window.addEventListener('message', function(event) { if (event.origin !== 'https://jetpack.wordpress.com') { return; } if (!event?.data?.iframeUniqueId && !event?.data?.height) { return; } const eventDataUniqueId = event.data.iframeUniqueId; // Change height for the matching comment iframe for (let i = 0; i < commentIframes.length; i++) { const iframe = commentIframes[i]; const url = new URL(iframe.src); const iframeUniqueIdParam = url.searchParams.get('iframe_unique_id'); if (iframeUniqueIdParam == event.data.iframeUniqueId) { iframe.style.height = event.data.height + 'px'; return; } } }); })(); {{{ ( 1 == data.settings.show_title ) ? '' + data.settings.title + '' : '' }}}

{{{ data.beforeForm }}} {{{ data.afterForm }}}
{{{ data.renderFieldsMarkedRequired() }}}
{{{ data.beforeFields }}} {{{ data.afterFields }}}
{{{ data.beforeField }}} {{{ data.afterField }}}
{{{ nfi18n.formHoneypot }}}
{{{ data.beforeField }}} <# /* * Render our input limit section if that setting exists. */ #>
<# /* * Render our error section if we have an error. */ #>
<# /* * Render any custom HTML after our field. */ #> {{{ data.afterField }}}
<# /* * This is our main field template. It's called for every field type. * Note that must have ONE top-level, wrapping element. i.e. a div/span/etc that wraps all of the template. */ #> <# /* * Render our label. */ #> {{{ data.renderLabel() }}} <# /* * Render our field element. Uses the template for the field being rendered. */ #>
{{{ data.renderElement() }}}
<# /* * Render our Description Text. */ #> {{{ data.renderDescText() }}}
{{{ data.renderElement() }}}
{{{ data.renderElement() }}}
<# if ( data.type === "listcheckbox" || data.type === "listradio" || data.type === "listimage" || data.type === "date" || data.type === "starrating" ) { #> {{{ ( data.maybeFilterHTML() === 'true' ) ? _.escape( data.label ) : data.label }}} {{{ ( 'undefined' != typeof data.required && 1 == data.required ) ? '*' : '' }}} {{{ data.maybeRenderHelp() }}} <# } else { #> {{{ ( data.maybeFilterHTML() === 'true' ) ? _.escape( data.label ) : data.label }}} {{{ ( 'undefined' != typeof data.required && 1 == data.required ) ? '*' : '' }}} {{{ data.maybeRenderHelp() }}} <# } #>
{{{ data.msg }}}
{{{ data.msg }}}
{{{ data.currentCount() }}} {{{ nfi18n.of }}} {{{ data.input_limit }}} {{{ data.input_limit_msg }}} <# let myType = data.type if('save'== data.type){ myType = 'button' } #> {{{ ( data.maybeFilterHTML() === 'true' ) ? _.escape( data.label ) : data.label }}}

More from this blog

Binarydiods

272 posts