8

I'm trying to automatically open a element when a containing is called by ID, for example: http://www.example.com/page.html#container. Ideally I'd like this to scroll to the point of the page where the is located (inside the summary element), and then open the details element. Obviously, the native scroll function works fine, but how can I set the details element to open?

Here's my HTML source:

<details class="concentration">
   <summary>
        <h4 id="sample-slug"><?php the_sub_field('emphasis_name'); ?></h4>
    </summary>

    <p><?php the_sub_field('emphasis_description'); ?></p>

    <div class="courses"><?php the_sub_field('emphasis_course_list'); ?></div>
</details>

When example.com/page.html#sample-slug is called, how can I make the details element aware of that and add the "open" attribute? I want to make sure the content is visible when the anchor is called.

Paulie_D
  • 107,962
  • 13
  • 142
  • 161
authorandrew
  • 145
  • 2
  • 10
  • First share your code, then ask the specific question. This question, as it's written, should be closed as offtopic. Read the help center to know more info. – Marcos Pérez Gude May 04 '16 at 16:37
  • I don't have any code, I'm asking if it's possible to be done without using Javascript. I don't know much about the
    element because it's pretty new. Do you want to see my HTML source?
    – authorandrew May 04 '16 at 16:39
  • In reading the guidelines, this is a perfectly acceptable question. I don't have code to share, I'm asking about the behavior of one HTML element, so the scope isn't ridiculous, and it's not open-ended or subjective. There's nothing in the guidelines that says I must include a code block, is there? – authorandrew May 04 '16 at 16:47

3 Answers3

11

I don't think you can open <details> with CSS alone. But you can:

  1. Get the hash with location.hash. Possibly listen to hashchange event.
  2. Use document.getElementById to get the element.
  3. Set its open property to true.

function openTarget() {
  var hash = location.hash.substring(1);
  if(hash) var details = document.getElementById(hash);
  if(details && details.tagName.toLowerCase() === 'details') details.open = true;
}
window.addEventListener('hashchange', openTarget);
openTarget();
:target {
  background: rgba(255, 255, 200, .7);
}
<details id="foo">Details <summary>Summary</summary></details>
<div><a href="#foo">#foo</a> <a href="#bar">#bar</a></div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Had just gotten to a similar spot and this worked a treat. I had included my code block (it's a little simpler) but it's working all right. – authorandrew May 04 '16 at 17:13
  • One further wrinkle, and I think this is connected to the event listener. When I initially load a page with a hash (http://www.mbts.edu/academics/masters-studies/mdiv/#preaching), the `
    ` element flashes (as per :target selector), but doesn't open. After the page has loaded, if I change the hash or click an in-text anchor,
    opens just fine. Am I correct that adding a second listener would correct this?
    – authorandrew May 04 '16 at 17:23
  • Adding `window.addEventListener('load', openDetails);` fixed this issue. Thanks for your solution! – authorandrew May 04 '16 at 18:48
  • I included the call `openTarget()` assuming the element would be already loaded, but yes, use a `DOMContentLoaded` or `load` event listener otherwise. – Oriol May 04 '16 at 19:04
  • 1
    This is only part of the answer - you'll also want to **scroll** to the inner element, so that user can see it. Scrolling is easy when you click on the link on the same page, which scrolls to some other part. But because it is a URL, it should also open up when you directly visit that hash url. Then you'll need to set `history.scrollRestoration = "manual"`. But you don't want to always do that - then you also have to handle scroll restoring for any page with/without any hash url. What you want to do is disable that restoration conditionally, scroll using js, then set it back to "auto". – bendtherules Oct 26 '20 at 14:47
  • With regards to previous comment - you **might** want to scroll manually. – bendtherules Oct 26 '20 at 14:57
1

Below I provide solution that works for nested <details><summary> elements:

With help of javascript you can:

  • track changes of hash anchor in url
  • react to them by changing open attribute of details elements accordingly

Here is example that does it, code here → https://stackoverflow.com/a/55377750/544721

details html element changing screencast

Grzegorz Wierzowiecki
  • 10,545
  • 9
  • 50
  • 88
0

Pure JS solution:

function openTarget() {
    const hash = location.hash.substring(1);
    if (hash) {
        const target = document.getElementById(hash);
        if (target) {
            const details = target.closest('details');
            if (details)
                details.open = true;
        }
    }
}
openTarget(); // onload
window.addEventListener('hashchange', openTarget);
Dmitry Shashurov
  • 1,148
  • 13
  • 11