w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 666 forks source link

Ability to style <details>/<summary> to be open (e.g. for print styles) #2084

Open patrickhlauke opened 6 years ago

patrickhlauke commented 6 years ago

(Not quite sure which spec this would relate to specifically, sorry)

If a page uses <details>/<summary> expand/collapse blocks, there currently appears to be no way to open these via CSS. This poses problems for print styling: if I wanted to have these blocks appear open when printed, it seems that the only solution is to first run JS over the document and add the open attribute on the <details>.

patrickhlauke commented 6 years ago

/cc @tabatkins @fantasai

Heydon commented 6 years ago

Would be great it was specified to be open for print media by default (which I guess is what you mean?)

patrickhlauke commented 6 years ago

Either that, or have some way to control it (like you'd want to control any other aspects when making decisions on how something should appear when printed). Currently, it's "style-resistant"...

Heydon commented 6 years ago

Aye, probably both.

iandevlin commented 6 years ago

Nice idea.

upsuper commented 6 years ago

I'm thinking about whether it is possible to describe the behavior of <details>/<summary> in CSS rather than having them being HTML rendering magic.

The most straightforward approach might be defining a new pseudo-element (something like ::details-content) for wrapping content in <details> other than the effective <summary>. But generally, browser vendors would be against adding this kind of pseudo-element wrapper, because they can bring lots of unnecessary complexity.

Maybe we can have that pseudo-element, but only allow display property with none or contents. This should make it easy to implement, I suppose.

tabatkins commented 6 years ago

I'm down with that approach. The UA stylesheet is then extremely trivial:

details::details-content { display: none; }
details[open]::details-content { display: contents; }

And overriding it is super easy. :+1: from me.

AmeliaBR commented 6 years ago

+1 to any strategy that makes it possible to describe the behavior of <details>/<summary> in standard CSS. It would make it much more useful in responsive design (e.g., for a collapsible menu) if you could auto-expand (and optionally hide the toggle <summary> button) when there is room for the full content.

Another way to approach this would be to have a generic selector for anonymous text nodes.

So the default style rule for <details>/<summary> would look something like:

details:not([open]) > *:not(summary),
details:not([open]) > *text* {
  /* any direct child elements other than summary, or any direct child text nodes */
  display: none;
}

There are other cases where it could be useful for authors to override default HTML renderings for anonymous text nodes, like <meter>/<progress>, where the anonymous text content inside is a formatted representation of the value, but is currently never rendered in supporting browsers.

A *text* selector could also simplify other browser styles, e.g. the way MS Edge adds a solid-color background to all anonymous text spans in high-contrast mode.

js-choi commented 6 years ago

@AmeliaBR I had been planning to propose pseudo-elements for anonymous text boxes, first to the WICG then eventually here. For instance, a pseudo-element for anonymous block boxes would be generally useful in other cases as an approximate analogue to HTML’s paragraphs, e.g., anonymous-block “paragraphs” such as those in <h1>First block</h1> This is the <em>second</em> block in this example. <p>This is the third.</p> <ul> <li>Fourth.</li> <li> <p>Fifth.</p> <p>Sixth.</p> </li> </ul>. Such pseudo-elements, however, might have broad ramifications for rendering performance, so I had planned on courting authors in the WICG before the CSSWG to bolster my case. This is the first mention of this idea I have yet seen elsewhere on the web, so it’s good to have another use case.

Having said all that, it is precisely the broadness in scope of such an anonymous-box selector that may make a ::details-content pseudo-element more feasible in the short term. An anonymous-box selector also may not actually match all of the non-summary content in a <details> element: <details> <summary>A</summary> <p> B <p> C </details>. I still do plan to make a formal proposal for anonymous-box selectors in general, unless someone else beats me to it.

jonjohnjohnson commented 6 years ago

Big fan of @tabatkins idea...

details::details-content { display: none; } details[open]::details-content { display: contents; }

But @Loirooriol, any idea how you could make this work with your ::contents proposal? Even if the summary is a child of the details element? I know there are cases where the tree is shuffled around for layout, like display: run-in?

As an aside, could we also get a ::details-marker pseudo element in the spec at the same time? I know webkit already has their own version, but it would be great to more seamlessly style the summary (or lack thereof) taking control over the generated contents arrow/marker. Could it be possible to steal the list items marker box ::marker pseudo element for reuse? Since it seems that...

Fully standards-compliant implementations automatically apply the CSS display: list-item to the summary element

But make the ::marker available even when details has no summary?

MDN Ref - ::-webkit-details-marker

AmeliaBR commented 6 years ago

As an aside, could we also get a ::details-marker pseudo element

The regular ::marker on the <summary> element will apply to it.

But make the ::marker available even when details has no summary?

In that case, it makes more sense to define a pseudoelement for the auto-generated summary toggle, and allow it to have stacked psuedoelements on it:

details::details-summary::marker,
details summary::marker {
  /* styles for the disclosure marker */
}
jonjohnjohnson commented 6 years ago

@AmeliaBR as well as something like this?

details::details-summary {
  content: 'Details';
  display: list-item;
}
AmeliaBR commented 6 years ago

@jonjohnjohnson Exactly! As I said earlier in the thread, I would very much like to get to the point where all of details/summary layout & rendering can be defined with a CSS model & customized by media queries. I hadn't been thinking about auto-generated summary toggles, but they definitely should be part of that.

Loirooriol commented 6 years ago

@jonjohnjohnson I don't think this would be a good fit for my ::contents proposal. Here you want to select only some children of the <details> but not the <summary>. The ::wrap proposal (#588) allows this bit doesn't seem a feasible feature, since it allows authors to produce non-tree DAGs.

there are cases where the tree is shuffled around for layout, like display: run-in

But this reparenting happens in the box tree. I think ::contents should live in the element tree just like ::before and ::after, so that things stay well-defined.

Then I think new pseudo-elements for detail parts would be better.

NickColley commented 6 years ago

I hope it's OK to chip in with an example of where this has stopped us from using details:

At GDS we were considering creating our new accordion component using details elements as it would allow for better functionality when JavaScript is not available, we're deciding not to use the element for now but I think if this were possible to style when printed we'd likely use it.

tabatkins commented 6 years ago

See also #3126, where Anne relays some requests for the ability to put ::before/::after in the contents of a details (so ::before comes after the summary, and they're both hidden when the details is closed); providing a ::details-content pseudo-element that allows ::before/::after on itself would also solve that problem.

chbndrhnns commented 5 years ago

I am making heavy use of these twisties for hiding diagrams or code snippets on markdown documentation pages (that get rendered to HTML). I have some styles that are activated when printing the document and for that purpose, I would also welcome a way to set <details> to open via pure CSS.

radogado commented 2 years ago

Hi, please add the ability to display by CSS, because I can't use the element in a responsive situation where it should always be open. Thanks.

toastal commented 2 years ago

I was hoping appearance: none would have helped me, but it seems like I need to reach for a JS solution. 😕

samuelbradshaw commented 2 years ago

+1. Another use case is to allow the open/closed state of the details element to be controlled by a preceding checkbox, using the sibling selector – something like

#agree-checkbox:checked + details {
  toggle-state: open;
}

Or a more general toggle to expand or collapse all details elements on the page:

#expand-all-checkbox:checked ~ details {
  toggle-state: open;
}
jonathantneal commented 2 years ago

With the recent additions of :open and :closed, I believe usage of the proposed pseudo-elements (for the shadow slot for details summary and for the shadow slot for details content) would look like this:

::details-content {
  /* styles the shadow slot for details content */
}

::details-summary {
  /* styles the shadow slot for details summary */
}

:open::details-summary {
  /* styles the shadow slot for details summary when it is open */
}

:closed::details-summary {
  /* style the shadow slot for details summary when it is closed */
}

:open::details-content {
  /* styles the shadow slot for details content when it is open */
}

:closed::details-content {
  /* styles the shadow slot for details content when it is closed */
}

The :open & :closed pseudo-states would select LightDOM elements (like <details>) matching either state, while the ::details-summary & ::details-content pseudo-elements would then cross the shadow boundary and select the shadow elements matching either term within <details>.

edent commented 2 years ago

Adding my voice to this. There's another issue with this - if a details box is closed, there's no way to navigate to its contents.

Here's a quick example:

<a href="#answer">What's in the box?</a>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<details>
   <summary>The box</summary>
   <div id="answer">A lovely surprise!</div>
</details>

I naïvely expected my browser to open the details and scroll me down to #answer.

Again, this would be particularly useful for answer accordions etc.

Boldewyn commented 2 years ago

I’ve detailed the use case from @edent’s comment a bit more in https://github.com/whatwg/html/issues/8509.

mariusGundersen commented 1 year ago

@tabatkins any progress on this?

yisibl commented 5 months ago

https://github.com/w3c/csswg-drafts/issues/9879#issuecomment-2121658036

RESOLVED: Use ::details-content as the name for the pseudo-element for the part of <details> that opens and closes

Boldewyn commented 5 months ago

Thank you for the pointer!

After reading the other issue (and two other linked ones) I’m still not sure how I would use ::details-content. Would it be something like this?

details ::details-content:has(:target) {
  display: block /* or inline, or use visibility? */;
}
yisibl commented 5 months ago

@Boldewyn I wrote a demo for ::details-content https://x.com/yisibl/status/1791452140663345300

clarfonthey commented 2 months ago

I'm down with that approach. The UA stylesheet is then extremely trivial:

details::details-content { display: none; }
details[open]::details-content { display: contents; }

And overriding it is super easy. 👍 from me.

Just wanna add that, at least currently, this does not seem to be the style used by chrome (and Firefox, as of version 130).

Simple example:

<style>
.grid {
    display: grid;
    grid-auto-flow: row dense;
    grid-template-columns: 1fr 1fr;
}
details {
    display: contents;
}
</style>
<div class="grid">
<details>
    <summary>summary 1</summary>
    <div>contents 1</div>
</details>
<details>
    <summary>summary 2</summary>
    <div>contents 2</div>
</details>

Here, we see that regardless of whether the details are open or not, the contents are included as a separate grid cell. If you add in additional <div> elements inside the contents, however, these will appear as multiple grid cells after opening, indicating that it is display: contents after being opened.

Personally, I would like this to be the default styles per the spec, but I think it's worth saying that it's not, at least implicitly per the behaviour we get when the details are closed.