Dialog styling with nested vanilla CSS

Hi, I've taken this code from Adam Argyle as a basis for styling my dialogs: dialog { /* Exit Stage To */ transform: translateY(-20px); &, &::backdrop { transition: display 1s allow-discrete, overlay 1s allow-discrete, opacity 1s ease, transform 1s ease; /* Exit Stage To */ opacity: 0; transform: translateY(20px); } /* On Stage */ &[open] { opacity: 1; transform: translateY(0px); display: flex; flex-direction: column; gap: 1rem; width: 750px; border-top: 1rem solid var(--color-matisse); max-width: calc(100% - 2rem); box-shadow: 0 0 1rem oklch(from var(--color-black) l c h / 0.5); padding: 1rem; &::backdrop { opacity: 0.8; } header { display: flex; align-items: start; gap: 1rem; button { position: absolute; top: 0; right: 0; } } html:has(&[open]) { overflow: hidden; scrollbar-gutter: stable; } /* Enter Stage From */ @starting-style { &[open], &[open]::backdrop { opacity: 0; } &[open] { transform: translateY(10px); } } &::backdrop { background-color: black; } } } I ahve another dialog that I am using for a mobile nav. This is styled totally independently so don't want these styles conflicting with it. As those styles (for the mobile nav) are specified after these ones, I COULD just overwrite all the properties, but that seems silly. Ideally i'd just like to stop these being applied to the nav so I tried adding :not(#mobile-nav) to the dialog selector, but it fails to work. Any ideas here?
81 Replies
ἔρως
ἔρως4w ago
I ahve another dialog that I am using for a mobile nav.
you're trying to fix bad solutions by monkey-patching css don't use a dialog for that
rctneil
rctneilOP4w ago
What's wrong with using a dialog for that? It's a piece of UI that appears.
ἔρως
ἔρως4w ago
it's not the right element for it
rctneil
rctneilOP4w ago
Either way, this isn;t really about whether a dialog is the right element ot use or not, this is about trying to resolve the issue.
ἔρως
ἔρως4w ago
there are "better" options
rctneil
rctneilOP4w ago
Ok, I agree it's the wrong element. Please help me fix the issue whilst keeping the mobile nav as the dialog. I agree, totally! Let's put that to the side and focus on the issue
ἔρως
ἔρως4w ago
if you really really really must use a dialog, set a data attribute
rctneil
rctneilOP4w ago
how will that help?
ἔρως
ἔρως4w ago
well, you add something like data-type="menu" or something then you only add the menu styles to data-type="menu" the xyz styles only for xyz this way, you don't have to override anything and just set the non-global styles where needed
rctneil
rctneilOP4w ago
So I should style my global dialog normally, and then on the mobile nav dialog reverse all those that do not apply?
ἔρως
ἔρως4w ago
no, have the styles for the mobile menu set under, for example, [data-type="menu"] and the styles for a form set under [data-type="form"] or something like this just the styles specific for that data-type
rctneil
rctneilOP4w ago
I don;t understand the need for the data attribute, the mobile nav had a unique id on it, surely that serves the same purpose?
ἔρως
ἔρως4w ago
or classes classes work too not exactly, but kinda you will need to do a fair bit of monkey patching on that css for that to work
rctneil
rctneilOP4w ago
I don't see the difference between using a data attribute and an id Please explain
ἔρως
ἔρως4w ago
the difference is that you don't have to override anything
rctneil
rctneilOP4w ago
How does that work? Can you provide an example?
ἔρως
ἔρως4w ago
no, not now, im playing overwatch what are the styles you need to put on the menu?
rctneil
rctneilOP4w ago
#mobile-nav { background: none; box-shadow: none; padding: 0; border-radius: 0; overflow: clip; inset: 0 0 0 auto; margin: 0 0 0 auto; block-size: 100dvh; max-block-size: 100%;
transition: display var(--_duration) allow-discrete, overlay var(--_duration) allow-discrete; &::backdrop { transition: opacity var(--_duration) var(--ease-4); opacity: 0; background-color: light-dark(#0003, #0008); cursor: zoom-out; } & > section { transition: translate var(--_duration) var(--ease-in-out-5); translate: 100% 0; } &[open] { &, &::backdrop { opacity: 1; }
& > section { opacity: 1; translate: 0; } } @starting-style { &[open], &[open]::backdrop { opacity: 0; } &[open] > section { opacity: 0; translate: 100% 0; } }
ἔρως
ἔρως4w ago
and what's not repeated for all?
rctneil
rctneilOP4w ago
I'm unsure right now
ἔρως
ἔρως4w ago
can you try to find out?
rctneil
rctneilOP4w ago
Surely the only way for me to acheive this is to style dialog one way, then to style #mobilenav by cancelling out any properties from the global ones that I don't want? Unless you know of a better way?
ἔρως
ἔρως4w ago
the better way is what i suggested before
rctneil
rctneilOP4w ago
but i'm confused as to what that "better way" is. I'm very intregued to know. If you can provide a very quick simple demo then i'd be more than hapy to take a look.
ἔρως
ἔρως4w ago
basically, just <dialog data-type="menu"> and in the css you add the menu-specific styles to &[data-type="menu"] { ... } and for the other dialogs, you use a different data-type this means that you won't need to override any other styles for anything or you can use classes or you can use css layers with the classes or attributes
rctneil
rctneilOP4w ago
Ah so not to style anything on just dialog? That means I need to add some sort of attribute, class etc onto all future dialogs.
ἔρως
ἔρως4w ago
yes
rctneil
rctneilOP4w ago
I see what you mean, but all future dialogs will be the same so need to be styled globally, it's just the menu one that is different
ἔρως
ἔρως4w ago
how do you know you won't use a different dialog?
rctneil
rctneilOP4w ago
Well obviously i don't but right now, in the scope of my app, I have two, the main type and the mobile nav type
ἔρως
ἔρως4w ago
what's the tech stack?
rctneil
rctneilOP4w ago
It's a rails app So, my original question still stands. Does anyone know of a way to acheive this by not overwirting or cancelling out the styles from global dialog to a more specific dialog? Most likely there isn;t but thought i'd ask?
ἔρως
ἔρως4w ago
yeah, rails doesn't have anything analogous to components, right?
rctneil
rctneilOP4w ago
Nope
ἔρως
ἔρως4w ago
yeah, my option is annoying af then you can try to see if you can use layers for this sounds like you should be able to
rctneil
rctneilOP4w ago
Not sure how layers can help. I'm already using layers
ἔρως
ἔρως4w ago
you can use a layer for the usual styles, and then another for the other styles i dont know how to explain, will experiment in a bit
rctneil
rctneilOP4w ago
They're already on separate layers, the styles for dialog are affecting #mobile-nav (as expected to be honest). Only way around this i can think of is to overwrite the ones in #mobile-nav` that don't need to be there
ἔρως
ἔρως4w ago
i will try some things
rctneil
rctneilOP4w ago
Ok, Look forward to seeing what you find
ἔρως
ἔρως4w ago
i couldn't come up with anything
rctneil
rctneilOP4w ago
ok thanks
clevermissfox
clevermissfox4w ago
:not(#mobile-nav) should work. Can you show an example of the selector you used that wasnt working? Also agree that dialog isn't the right element for a nav though, it's hidden from the accessibility tree until it's triggered and into the top layer of the dom.
ἔρως
ἔρως4w ago
it also steals the focus onto the dialog itself, if there's nothing that sets the focus automatically, which is utterly useless
rctneil
rctneilOP4w ago
I thought the :not selector should work and that's what I wanted to discuss but @ἔρως kept pushing the conversation around to correct/incorrect usage of the <dialog> element. My selector is dialog:not(#mobile-nav) {, further down, and nested within that, I have &[open]. These styles are in one layer, and my #mobile-nav styles are in a higher layer. On the subject of the use of <dialog> here, can we park this in this topic and stay on track. Whether you think the use is right or wrong for this situation, right here, right now, I do not care. It is a valid discussion and I am more than happy to start another thread to discuss that but let's stay on topic and discuss why the selector I have written is not working. Fair? I'd appreciate any discussion and comments from anyone about how we can solve this.
ἔρως
ἔρως4w ago
it works, it just kills the styles for EVERYTHING and you have to re-style everything again, if you used a different element for the menu, you wouldnt have to faf about like this
rctneil
rctneilOP4w ago
What do you mean by “it works, it just kills the styles for EVERYTHING?”
ἔρως
ἔρως4w ago
the selector does "the thing", but by doing "the thing" it is only styling the other dialogs and not the one in the headed
rctneil
rctneilOP4w ago
But it doesn’t! That’s the whole reason I am posting here.
ἔρως
ἔρως4w ago
🤔 i need to see that is there a live example somewhere?
rctneil
rctneilOP4w ago
I'll work on one and post back
13eck
13eck4w ago
Pro-tip: use three backticks to create a code block (instead of doing single-backticks on each line). See #How To Ask Good Questions for the correct syntax
ἔρως
ἔρως4w ago
ive quickly tested on jsfiddle and the selector should work - https://jsfiddle.net/pf7eoxd8/ ive simulated everything i could in as little code because lazy
rctneil
rctneilOP4w ago
I'll build a demo this evening
ἔρως
ἔρως4w ago
alright
Chris Bolson
Chris Bolson4w ago
I might be misunderstanding the original question but couldn't you reset the dialog styles with inital?
dialog#mobile-nav{
all: inital;
... nav specific CSS styling
}
dialog#mobile-nav{
all: inital;
... nav specific CSS styling
}
ἔρως
ἔρως4w ago
i think there are animations and stuff that's shared between both types of dialogs
rctneil
rctneilOP4w ago
Actually that’s a good shout. I may try that. There is nothing shared between them. It’s just I want global dialog styles and then ones specific for this mobile nav so that may be a solution. As I said I’ll try to build a demo and have a play with all: initial. Appreciate the suggestion!
Chris Bolson
Chris Bolson4w ago
Quick demo using your CSS from this thread https://codepen.io/cbolson/pen/xbxXRez (will delete later)
rctneil
rctneilOP4w ago
Awesome. Thanks @Chris Bolson
Chris Bolson
Chris Bolson4w ago
The dialog:not(#mobile-nav) suggestion by Clevermissfox should also work. Also, placing them in separate layers should have worked too (it did in my test)
rctneil
rctneilOP4w ago
Maybe my code got a bit out of wack. I'll try to tidy it up and see how I get on
Chris Bolson
Chris Bolson4w ago
I know the feeling 😆
rctneil
rctneilOP4w ago
Slowly making progress with this, but a related question. @Chris Bolson In this demo here: https://codepen.io/argyleink/pen/jOgxGmX Any idea how I can make the animation come in from the right hand side? I've swapped all the appropriate properties but the "translate from right" is messed up. Any suggestions?
rctneil
rctneilOP4w ago
This is my fork where I tried switching it to the right: https://codepen.io/rctneil/pen/EaxwbLG
Chris Bolson
Chris Bolson3w ago
Why don't you translate the whole dialog rather than just the contents?
rctneil
rctneilOP3w ago
@Chris Bolson That is exactly what I asked Adam Argyle on Blue Sky earlier today (https://bsky.app/profile/rctneil.co.uk/post/3lk45csp74k2w) It confused me. I've managed to put this toegther which is super close to what I am after: https://codepen.io/rctneil/pen/VYwMXmO?editors=1100 Just unsure why, when closing, it jumps downwards a little in Safari?
clevermissfox
clevermissfox3w ago
Your nested selector is computing to dialog:not(#mobile-nav)[open] which isn’t valid. You can rewrite it in a couple of ways but essentially you need dialog[open]:not(#mobile-nav)
ἔρως
ἔρως3w ago
actually, it is valid here, you can see that it does work i've used different tags and attributes and a different id, but the result is the same at the end, the span is being matching by p:not(#sport)[data-x="1"] span the order kinda sorta doesn't matter
rctneil
rctneilOP3w ago
Anyone have any ideas how to get rid of the closing jump in Safari?
ἔρως
ἔρως3w ago
i dont use anything apple - too rich for my blood and for my wallet
clevermissfox
clevermissfox3w ago
Aha Ive used the wrong ID #mobile-nav not #mobileNav . You’re right it should work 🤔 maybe some specificity issue then . I would look in the dev tools to see if it identifies an error with the syntax or if there’s a style somewhere you’ve forgotten about that’s overwriting
rctneil
rctneilOP3w ago
Will do. My current task is a bit away from that, just trying to complete the dialog panel I liked to in the codepen. Then i'll go back and style the regular dialogs where I may his this issue again!
Chris Bolson
Chris Bolson3w ago
It could be the timing function that you are using. Try something simpler to see if that resolves the jumping issue.
rctneil
rctneilOP3w ago
Nope, changing the easing doesn't help. Very weird
Chris Bolson
Chris Bolson3w ago
Try adding top: 0; to the dialog
rctneil
rctneilOP3w ago
That does it. Not sure why though as it's not absolutely positioned.
clevermissfox
clevermissfox3w ago
Default styles of a dialog do include position absolute , there are a handful of default styles that exist unless you override
rctneil
rctneilOP3w ago
So all looks good apart from Firefox where it works fine but on close it just vanishes and doesn't animate out. I can live with that. I think it's a lack of support for allow-discrete.
Chris Bolson
Chris Bolson3w ago
yes, that won't work in FF yet
rctneil
rctneilOP3w ago
Not a major issue

Did you find this page helpful?