{"id":340,"date":"2026-08-13T21:05:10","date_gmt":"2026-08-13T21:05:10","guid":{"rendered":"https:\/\/webaffair.net\/blog\/?p=340"},"modified":"2026-08-13T21:06:27","modified_gmt":"2026-08-13T21:06:27","slug":"javascript-free-inline-hide-spoiler-tags","status":"publish","type":"post","link":"https:\/\/webaffair.net\/blog\/code\/javascript-free-inline-hide-spoiler-tags\/","title":{"rendered":"Javascript-Free Inline Hide Spoiler Tags"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The basic related html is:<\/p>\n\n\n\n<pre class=\"wp-block-code html\"><code>&lt;details class=\"spoiler\"&gt;This text is hidden&lt;\/details&gt;<\/code><\/pre>\n\n\n\n<style data-wp-block-html=\"css\">\ndetails.spoiler {\n    display: inline-block;\n    background: #999;\n    padding: 0 0.4em;\n    color: transparent;\n}\ndetails.spoiler[open] {\n    background: #a0a0a0;\n}\ndetails.spoiler[open]::details-content {\n    margin-top: -1.15em;\n    color: black;\n    pointer-events: none;\n}\n<\/style>\n\nGiving you this: <details class=\"spoiler\">This text is hidden<\/details>\n\n\n\n<p class=\"wp-block-paragraph\">This will also work with this html:<\/p>\n\n\n\n<pre class=\"wp-block-code html\"><code>&lt;details class=\"spoiler\"&gt;&lt;summary&gt;Spoiler&lt;\/summary&gt;This text is hidden&lt;\/details&gt;<\/code><\/pre>\n\n\n\n<style data-wp-block-html=\"css\">\ndetails.spoiler {\n    display: inline-block;\n    background: #999;\n    padding: 1px 0.4em;\n    color: transparent;\n}\ndetails.spoiler[open] {\n    background: #a0a0a0;\n    position: relative;\n}\ndetails.spoiler:not([open]) summary {\n   color: black;\n   display: inline;\n   padding: 0 0.4em;\n   font-variant: all-small-caps;\n}\ndetails.spoiler[open]::details-content {\n    margin-top: -1.15em;\n    color: black;\n    pointer-events: none;\n}\n<\/style>\n\nGiving you this: <details class=\"spoiler\"><summary>Spoiler<\/summary>This text is hidden<\/details>\n\n\n\n<h2 class=\"wp-block-heading\">How I did it:<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Step 1: Make the details tag flow inline with the content, and give it a background color. <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I figured out this worked with inline-block rather than inline, and I also added a bit of padding because it ended up looking nicer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\"><strong>Careful:<\/strong><\/mark> By the HTML specs, you cannot put a &lt;details&gt; tag inside a &lt;p&gt; tag, regardless of it&#8217;s display: directive &#8211; doing so will automatically close the paragraph tag, and the spoiler will end up on it&#8217;s own line regardless. It will however still work. Putting this inside a div, table cell, or other container for your text works fine.<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler {\n    display: inline-block;\n    background: #999;\n    padding: 0 0.4em;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Step 2: Hide the summary text, while having it continue to take up the same amount of space, and remain focusable\/clickable<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The styles used need to be applied to the details tag, because there&#8217;s no other way to style the auto-inserted summary. color:transparent makes the text invisible, while having it take up the same amount of space (unlike font-size: 0) and keeping it a focusable element with the on-click behaviour intact (unlike visibility: hidden).<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler {\n    color: transparent;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Step 3: Bring the content up to the top line of the details box when expanded, rather than sitting below the (still hidden) summary text. <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A negative margin-top does the trick; the exact value needs to scale with the line-height of the surrounding text. Alternately, you could specify a line-height on the details tag itself, and not worry about perfectly matching the surrounding text; at least that way it&#8217;s guaranteed not to overhang the grey box one direction or another.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We also need to reverse the color: transparent so that the content itself is visible, and a lighter shade of grey brings the text contrast into something appropriate. Keeping a background color set at all makes it more obvious that the user can still interact with it, and also will keep the contrast workable if it is being displayed on a dark background, since we can&#8217;t use inherit to get the surrounding text&#8217;s color (it would just inherit the details tag&#8217;s transparency).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The ::details-content pseudo-element will select all of the contents of the details box except for the summary (either specified or implied). (Too bad there&#8217;s no ::details-summary pseudo element to select the auto-inserted Details text directly, even though there is an element in the Shadow DOM, but we work with what we&#8217;ve got.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Caution:<\/mark><\/strong> Styling details-content while the details tag is closed has some weird effects, so specifying [open] makes sure we don&#8217;t do that. Using the :open state would presumably be marginally faster than checking for an attribute, but that&#8217;s not yet fully implemented cross-browser, and no human is going to notice the difference in page load speed.<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler&#91;open] {\n    background: #a0a0a0;\n}\ndetails.spoiler&#91;open]::details-content {\n    margin-top: -1.15em; \/* this needs to match the line-height *\/\n    color: black;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Step 4: Make it so that clicking on the spoiler again triggers the collapse, rather than being treated as a click in the content which doesn&#8217;t do anything.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">pointer-events: none will make the contents ignore any click events and instead pass it through to whatever is directly below it as if it was not present. In this case, the transparent summary is still underneath, since we just moved the contents on top of it, and clicking on that will &#8220;collapse&#8221; the spoiler again, which is exactly what I want.<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler&#91;open]::details-content {\n    pointer-events: none; \n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Step 5: If the &lt;summary> tag is used, make it show, but only when the details tag is collapsed.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There&#8217;s no [closed] or :closed option to target, but :not() will do the trick nicely.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">display: inline will also make the triangular list-marker disappear. For some reason you can&#8217;t put display:none on a ::marker pseudo-element (at least not in Chrome), but this works.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Adding a bit more padding here looks better in my opinion; adjust to taste.<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler:not(&#91;open]) summary {\n    color: black;\n    display: inline; \n    padding: 0 0.4em;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">The complete code:<\/h2>\n\n\n\n<pre class=\"wp-block-code css\"><code>details.spoiler {\n    display: inline-block;\n    background: #999;\n    padding: 0 0.4em;\n    color: transparent;\n    line-height: 1.15;\n}\ndetails.spoiler&#91;open] {\n    background: #a0a0a0;\n}\ndetails.spoiler:not(&#91;open]) summary {\n    color: black;\n    display: inline;\n    padding: 0 0.4em;\n}\ndetails.spoiler&#91;open]::details-content {\n    margin-top: -1.15em;\n    color: black;\n    pointer-events: none;\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The basic related html is: Giving you this: This text is hidden This will also work with this html: Giving you this: Spoiler This text is hidden How I did it: Step 1: Make the details tag flow inline with the content, and give it a background color. I figured out this worked with inline-block&#8230; <a class=\"read-more\" href=\"https:\/\/webaffair.net\/blog\/code\/javascript-free-inline-hide-spoiler-tags\/\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[21,3],"tags":[18,40],"class_list":["post-340","post","type-post","status-publish","format-standard","hentry","category-basics","category-code","tag-css","tag-html"],"jetpack-related-posts":[{"id":115,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/using-svg-filters-in-css\/","url_meta":{"origin":340,"position":0},"title":"Using SVG Filters in CSS","author":"Jay","date":"June 2, 2024","format":false,"excerpt":"Firstly, you'll need the svg itself. <svg style=\"height:0; overflow:hidden;\"> <defs> <filter id=\"wavy2\"> <feTurbulence x=\"0\" y=\"0\" baseFrequency=\"0.02\" numOctaves=\"5\" seed=\"1\"><\/feTurbulence> <feDisplacementMap in=\"SourceGraphic\" scale=\"20\"><\/feDisplacementMap> <\/filter> <filter id=\"goo\"><feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"8\" result=\"blur\"><\/feGaussianBlur> <feColorMatrix in=\"blur\" mode=\"matrix\" values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9\"\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":317,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/introduction-to-browser-development-tools\/","url_meta":{"origin":340,"position":1},"title":"Introduction to Browser Development Tools","author":"Jay","date":"December 18, 2025","format":false,"excerpt":"All modern desktop browsers now have integrated browser tools, however, there are subtle (and sometimes less subtle) differences between each. I find that Firefox has the best overall, though I do switch to Chrome for some specific debugging tasks. I personally only use Edge or Safari when trying to isolate\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":250,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/responsive-font-sizes-title-bars\/","url_meta":{"origin":340,"position":2},"title":"Responsive Font Sizes &amp; Title Bars","author":"Jay","date":"November 20, 2025","format":false,"excerpt":"Let's say we want a reall big, chunky main title for our forum skin. Here's, I think, the simplest way to do it, I see this a lot: .maintitle { height: 160px; line-height: 160px; text-align: center; font-size: 40px; } If we add that to the stylesheet and check it on\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":49,"url":"https:\/\/webaffair.net\/blog\/code\/snippets\/my-favourite-text-gradients\/","url_meta":{"origin":340,"position":3},"title":"My Favourite Text Gradients","author":"Jay","date":"September 26, 2021","format":false,"excerpt":"Note: I am using -webkit prefixed styles for all three relevant rules to ensure that only browsers that implement all three will load the background gradient at all. I could use a proper polyfill and\/or @supports, but honestly this creates more readable code. Non-webkit browsers have started using webkit prefixes\u2026","rel":"","context":"In &quot;Snippets and Notes&quot;","block_context":{"text":"Snippets and Notes","link":"https:\/\/webaffair.net\/blog\/category\/code\/snippets\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":11,"url":"https:\/\/webaffair.net\/blog\/portfolio\/current\/the-book-of-traceable-heraldic-art\/","url_meta":{"origin":340,"position":4},"title":"The Book of Traceable Heraldic Art","author":"Jay","date":"September 16, 2021","format":false,"excerpt":"This is a complete rebuild of the back end of an existing website. The old site had a complex build process was but then serving static html pages. I am rebuilding it as a node.js site with a MongoDB back end.","rel":"","context":"In &quot;Current Projects&quot;","block_context":{"text":"Current Projects","link":"https:\/\/webaffair.net\/blog\/category\/portfolio\/current\/"},"img":{"alt_text":"Book of Traceable Heraldic Art","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2021\/09\/cover-page.pdf.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":137,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/ajax-and-images\/","url_meta":{"origin":340,"position":5},"title":"AJAX and Images","author":"Jay","date":"June 22, 2024","format":false,"excerpt":"Okay so I recently figured this out, fixed it on my scripts, forgot about it, was just reminded, realized I ought to document\/share. So this is getting posted here and a couple other places. When you do a fetch() or $.get() the browser only fetches that specific page, and doesn't\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/340","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/comments?post=340"}],"version-history":[{"count":2,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/340\/revisions"}],"predecessor-version":[{"id":342,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/340\/revisions\/342"}],"wp:attachment":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/media?parent=340"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/categories?post=340"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/tags?post=340"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}