From 186fde29718d0632b6d107e60700fd09fa9d7198 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 16 Jan 2025 15:29:00 +0100 Subject: [PATCH 01/16] Flyout: define `position="inline"` Allow theme developers to define `position="inline"` to adapt the flyout to its container. It uses `bottom: 0` to make it open up side, and it should probably use `top: 0` to make it open down side. --- src/flyout.css | 14 ++++++++++++++ src/flyout.js | 4 +--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index df23523a..17ef910b 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -40,6 +40,20 @@ top: 50px; } +.container.inline { + width: 100%; + padding: 0; + margin: 0; + position: absolute; + bottom: 0; +} + +@media screen and (max-width: 768px) { + .container.inline { + max-width: 100%; + } +} + :host > div { font-family: var( --readthedocs-flyout-font-family, diff --git a/src/flyout.js b/src/flyout.js index 45c13ec2..b782acc4 100644 --- a/src/flyout.js +++ b/src/flyout.js @@ -26,7 +26,6 @@ export class FlyoutElement extends LitElement { static properties = { config: { state: true }, opened: { type: Boolean }, - floating: { type: Boolean }, position: { type: String }, }; @@ -37,7 +36,6 @@ export class FlyoutElement extends LitElement { this.config = null; this.opened = false; - this.floating = true; this.position = "bottom-right"; this.readthedocsLogo = READTHEDOCS_LOGO; } @@ -327,7 +325,7 @@ export class FlyoutElement extends LitElement { } updateCSSClasses() { - this.classes = { floating: this.floating, container: true }; + this.classes = { container: true }; this.classes[this.position] = true; } From 9c8806df07cc155877328e476d527dc16559f61e Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 16 Jan 2025 15:42:27 +0100 Subject: [PATCH 02/16] Add some padding to the flyout respecting the container --- src/flyout.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index 17ef910b..eb6df53b 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -41,8 +41,8 @@ } .container.inline { - width: 100%; - padding: 0; + width: calc(100% - 20px); + padding: 0 10px; margin: 0; position: absolute; bottom: 0; From c242b5099686aa13e2c5ab108c26c6d90299403b Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 16 Jan 2025 17:02:09 +0100 Subject: [PATCH 03/16] Update tests to pass --- tests/__snapshots__/flyout.test.snap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/__snapshots__/flyout.test.snap.js b/tests/__snapshots__/flyout.test.snap.js index 8fae30c0..460bc054 100644 --- a/tests/__snapshots__/flyout.test.snap.js +++ b/tests/__snapshots__/flyout.test.snap.js @@ -2,7 +2,7 @@ export const snapshots = {}; snapshots["Flyout addon snapshot flyout completely"] = -`
+`
Read the Docs +`
Read the Docs Date: Mon, 20 Jan 2025 05:19:22 -0800 Subject: [PATCH 04/16] Use inline positioning instead of absolute (#501) Here is a quick example of using inline positioning. I've reused `top-left` position to indicate "downward expanding menu" but this could be something more explicit. It would be nice as `position="inline down"` perhaps. There are two basic examples, one truly inline and one flyout inside a mock sidebar menu -- just to illustrate a theme maintainer nesting the flyout element inside another element. The tricky part here is making the `main` menu "float" over other content, and we use `overflow: visible` and absolute positioning to allow content to reflow around the element. There are some fixes required here: too narrow of a parent clips the collapsed menu, we probably want a max width on the popup menu (keeping the collapsed menu width 100% (this is to fill the parent element). https://github.com/user-attachments/assets/413d7c03-38d3-48e0-a88a-4cf53cc8dd92 --- public/index.html | 23 +++++++++++++++++++++++ src/flyout.css | 35 ++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/public/index.html b/public/index.html index f24ff41a..69f8bc73 100644 --- a/public/index.html +++ b/public/index.html @@ -37,6 +37,29 @@

Ethical Ad

CustomScript

Content of the section

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+
+ +
+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+ +
+ +
+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

+

Hit / to trigger the search modal, or click on the input from the flyout.

diff --git a/src/flyout.css b/src/flyout.css index eb6df53b..050c98c2 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -20,32 +20,34 @@ line-height: var(--addons-flyout-line-height); } -.container.bottom-right { +.container.bottom-right:not(.inline) { right: 20px; bottom: 50px; } -.container.bottom-left { +.container.bottom-left:not(.inline) { left: 20px; bottom: 50px; } -.container.top-left { +.container.top-left:not(.inline) { left: 20px; top: 50px; } -.container.top-right { +.container.top-right:not(.inline) { right: 20px; top: 50px; } .container.inline { width: calc(100% - 20px); + max-width: 100%; padding: 0 10px; margin: 0; - position: absolute; - bottom: 0; + position: relative; + display: inline-block; + overflow: visible; } @media screen and (max-width: 768px) { @@ -130,7 +132,26 @@ main { margin-top: 5px; } -main.closed { +.container.inline main { + position: absolute; + bottom: 3em; + padding: 1em; + background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); +} + +/* This is where `.container.top-left` would be better as `.container.top.left`, giving an independent `top` */ +.container.bottom-left.inline main, +.container.bottom-right.inline main { + bottom: 3em; + top: unset; +} +.container.top-left.inline main, +.container.top-right.inline main { + top: 3em; + bottom: unset; +} + +main.closed, .container.inline main.closed { display: none; } From f95fae5bf5d3289cc06152d4ce965d35a9a1ccf8 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 20 Jan 2025 14:20:38 +0100 Subject: [PATCH 05/16] I added my changes --- public/index.html | 45 ++++++++++++++++++++++++++++----------------- src/flyout.css | 24 +++++++++--------------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/public/index.html b/public/index.html index 69f8bc73..502ca608 100644 --- a/public/index.html +++ b/public/index.html @@ -37,28 +37,39 @@

Ethical Ad

CustomScript

Content of the section

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

+

Flyout

+ +

+ Lorem ipsum odor amet, consectetuer adipiscing elit. Ultricies massa + molestie per iaculis id cras fermentum mi fames. Feugiat per cubilia + volutpat; dictumst cras libero fringilla. +

+
- +
-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

+ +

+ Placerat conubia vivamus finibus + vulputate, sit ipsum. Senectus netus aptent laoreet per venenatis maximus. + Praesent mi tellus congue orci mus in etiam suspendisse. Inceptos senectus + nam accumsan, praesent felis consequat feugiat maximus. Dolor cras + faucibus sociosqu feugiat urna orci integer hendrerit. +

+
- +
-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

-

Hit / to trigger the search modal, or click on the input from the flyout.

+ + + + +

+ Felis mus quis urna consequat arcu blandit finibus dui. Rutrum fames + aliquet nunc vitae aenean class mattis elit. Quis pretium himenaeos + facilisis sodales molestie fringilla ac interdum. +

Hit / to trigger the search modal, or click on the input from the flyout.

diff --git a/src/flyout.css b/src/flyout.css index 050c98c2..82d25110 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -41,8 +41,7 @@ } .container.inline { - width: calc(100% - 20px); - max-width: 100%; + width: 100%; padding: 0 10px; margin: 0; position: relative; @@ -50,12 +49,6 @@ overflow: visible; } -@media screen and (max-width: 768px) { - .container.inline { - max-width: 100%; - } -} - :host > div { font-family: var( --readthedocs-flyout-font-family, @@ -137,21 +130,22 @@ main { bottom: 3em; padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); + margin-left: -0.6rem; + width: calc(100% - 1.6rem); } -/* This is where `.container.top-left` would be better as `.container.top.left`, giving an independent `top` */ -.container.bottom-left.inline main, -.container.bottom-right.inline main { +.container.bottom.inline main { bottom: 3em; top: unset; } -.container.top-left.inline main, -.container.top-right.inline main { - top: 3em; + +.container.top.inline main { + top: 2.85em; bottom: unset; } -main.closed, .container.inline main.closed { +main.closed, +.container.inline main.closed { display: none; } From 55ab85635dee7de67f0dffc7c70fe1bc76957909 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 20 Jan 2025 14:31:46 +0100 Subject: [PATCH 06/16] Rename CSS classes --- public/index.html | 4 ++-- src/flyout.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/index.html b/public/index.html index 502ca608..1b5b75ba 100644 --- a/public/index.html +++ b/public/index.html @@ -46,7 +46,7 @@

Flyout

- +

@@ -59,7 +59,7 @@

Flyout

- +
diff --git a/src/flyout.css b/src/flyout.css index 82d25110..a40f75f2 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -134,12 +134,12 @@ main { width: calc(100% - 1.6rem); } -.container.bottom.inline main { +.container.down.inline main { bottom: 3em; top: unset; } -.container.top.inline main { +.container.up.inline main { top: 2.85em; bottom: unset; } From 60b9e33eae8377988b0e6ae0316085d5732e8967 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 20 Jan 2025 14:32:27 +0100 Subject: [PATCH 07/16] Increase the size of the container and grow with it --- public/index.html | 2 +- src/flyout.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 1b5b75ba..25aeda51 100644 --- a/public/index.html +++ b/public/index.html @@ -58,7 +58,7 @@

Flyout

-
+
diff --git a/src/flyout.css b/src/flyout.css index a40f75f2..470080b6 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -42,6 +42,7 @@ .container.inline { width: 100%; + max-width: 100%; padding: 0 10px; margin: 0; position: relative; From 3372883b61c24b233970b29738d7187a17ea40c9 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 20 Jan 2025 15:47:34 +0100 Subject: [PATCH 08/16] Fix down/up openings --- public/index.html | 4 ++-- src/flyout.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/index.html b/public/index.html index 25aeda51..794fb884 100644 --- a/public/index.html +++ b/public/index.html @@ -46,7 +46,7 @@

Flyout

- +

@@ -59,7 +59,7 @@

Flyout

- +
diff --git a/src/flyout.css b/src/flyout.css index 470080b6..e677ff8d 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -135,12 +135,12 @@ main { width: calc(100% - 1.6rem); } -.container.down.inline main { +.container.up.inline main { bottom: 3em; top: unset; } -.container.up.inline main { +.container.down.inline main { top: 2.85em; bottom: unset; } From fa162e564dd0aa786bd7820f0435562c2ae8dd98 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 20 Jan 2025 16:35:16 +0100 Subject: [PATCH 09/16] adjustments for Sphinx Furo theme --- src/flyout.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index e677ff8d..5eaff6fe 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -43,6 +43,8 @@ .container.inline { width: 100%; max-width: 100%; + height: 100%; + max-height: 100%; padding: 0 10px; margin: 0; position: relative; @@ -128,15 +130,15 @@ main { .container.inline main { position: absolute; - bottom: 3em; padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); - margin-left: -0.6rem; - width: calc(100% - 1.6rem); + bottom: 3em; + width: calc(100% - (var(--addons-flyout-font-size) * 2)); + margin-left: calc(var(--addons-flyout-font-size) - 1.3rem); } .container.up.inline main { - bottom: 3em; + bottom: calc(var(--addons-flyout-font-size) * 3.2); top: unset; } From 721cfa73bdc482edbb91d5b4590f99288b4f8632 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 21 Jan 2025 12:34:35 +0100 Subject: [PATCH 10/16] Caculated properties are not needed --- src/flyout.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index 5eaff6fe..f9028c21 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -134,11 +134,12 @@ main { background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); bottom: 3em; width: calc(100% - (var(--addons-flyout-font-size) * 2)); - margin-left: calc(var(--addons-flyout-font-size) - 1.3rem); + + /* Remove the padding-left added in .container.inline */ + margin-left: -10px; } .container.up.inline main { - bottom: calc(var(--addons-flyout-font-size) * 3.2); top: unset; } From bf6962ccff32432fc554ea1e65c6b94659372304 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 21 Jan 2025 12:35:26 +0100 Subject: [PATCH 11/16] Calculated width is not neeed here --- src/flyout.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/flyout.css b/src/flyout.css index f9028c21..4b50a13d 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -133,7 +133,6 @@ main { padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); bottom: 3em; - width: calc(100% - (var(--addons-flyout-font-size) * 2)); /* Remove the padding-left added in .container.inline */ margin-left: -10px; From 4af9427b20895258de8bce1fd3c5a58232a10b1a Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 21 Jan 2025 13:21:48 +0100 Subject: [PATCH 12/16] Use JavaScript to calculate `margin-bottom` based on `main`'s height --- src/flyout.css | 2 +- src/flyout.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/flyout.css b/src/flyout.css index 4b50a13d..683f53a5 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -132,7 +132,6 @@ main { position: absolute; padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); - bottom: 3em; /* Remove the padding-left added in .container.inline */ margin-left: -10px; @@ -140,6 +139,7 @@ main { .container.up.inline main { top: unset; + bottom: 0; } .container.down.inline main { diff --git a/src/flyout.js b/src/flyout.js index b782acc4..bd384c60 100644 --- a/src/flyout.js +++ b/src/flyout.js @@ -329,6 +329,22 @@ export class FlyoutElement extends LitElement { this.classes[this.position] = true; } + updated() { + // Update the `margin-bottom` property for the main part of the flyout, + // to display it exactly over the header of the flyout. + // I understand this is not possible to do with CSS, so we use JavaScript for it. + const main = this.renderRoot.querySelector("main"); + const header = this.renderRoot.querySelector("header"); + if (this.position.includes("up") && main !== null && header !== null) { + console.log(header.clientHeight); + console.log(header.getBoundingClientRect().height); + main.style.setProperty( + "margin-bottom", + `${header.getBoundingClientRect().height}px`, + ); + } + } + render() { // The element doesn't yet have our config, don't render it. if (this.config === null) { From 49e6b4e22cbc8ce4391ab19281453c49c54700b3 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 21 Jan 2025 13:30:27 +0100 Subject: [PATCH 13/16] Same for `.down` class --- src/flyout.css | 2 +- src/flyout.js | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index 683f53a5..dd43711c 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -143,7 +143,7 @@ main { } .container.down.inline main { - top: 2.85em; + top: 0; bottom: unset; } diff --git a/src/flyout.js b/src/flyout.js index bd384c60..599721eb 100644 --- a/src/flyout.js +++ b/src/flyout.js @@ -335,13 +335,20 @@ export class FlyoutElement extends LitElement { // I understand this is not possible to do with CSS, so we use JavaScript for it. const main = this.renderRoot.querySelector("main"); const header = this.renderRoot.querySelector("header"); - if (this.position.includes("up") && main !== null && header !== null) { - console.log(header.clientHeight); - console.log(header.getBoundingClientRect().height); - main.style.setProperty( - "margin-bottom", - `${header.getBoundingClientRect().height}px`, - ); + if (main !== null && header !== null) { + if (this.position.includes("up")) { + main.style.setProperty( + "margin-bottom", + `${header.getBoundingClientRect().height}px`, + ); + } + + if (this.position.includes("down")) { + main.style.setProperty( + "margin-top", + `${header.getBoundingClientRect().height}px`, + ); + } } } From 8acadc33ceb4065ce77c1d63b7d3eea01d5a88e7 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 21 Jan 2025 13:47:09 +0100 Subject: [PATCH 14/16] Keep `width` because is required in some scenarios --- public/index.html | 2 +- src/flyout.css | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 794fb884..204de9f2 100644 --- a/public/index.html +++ b/public/index.html @@ -45,7 +45,7 @@

Flyout

volutpat; dictumst cras libero fringilla.

-
+
diff --git a/src/flyout.css b/src/flyout.css index dd43711c..386af451 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -133,8 +133,11 @@ main { padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); - /* Remove the padding-left added in .container.inline */ + /* Remove the padding-left added in `.container.inline` */ margin-left: -10px; + + /* Use full width minus 1em padding added on left and right in `.container.inline main` */ + width: calc(100% - 2em); } .container.up.inline main { From 4e40ec29fe8cab060ef836f64dcf0154ff1c5ef6 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 23 Jan 2025 11:30:15 +0100 Subject: [PATCH 15/16] Remove JS hack code --- src/flyout.css | 11 ----------- src/flyout.js | 23 ----------------------- 2 files changed, 34 deletions(-) diff --git a/src/flyout.css b/src/flyout.css index 386af451..8d0e4c41 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -129,7 +129,6 @@ main { } .container.inline main { - position: absolute; padding: 1em; background-color: var(--readthedocs-flyout-background-color, rgb(39, 39, 37)); @@ -140,16 +139,6 @@ main { width: calc(100% - 2em); } -.container.up.inline main { - top: unset; - bottom: 0; -} - -.container.down.inline main { - top: 0; - bottom: unset; -} - main.closed, .container.inline main.closed { display: none; diff --git a/src/flyout.js b/src/flyout.js index 599721eb..b782acc4 100644 --- a/src/flyout.js +++ b/src/flyout.js @@ -329,29 +329,6 @@ export class FlyoutElement extends LitElement { this.classes[this.position] = true; } - updated() { - // Update the `margin-bottom` property for the main part of the flyout, - // to display it exactly over the header of the flyout. - // I understand this is not possible to do with CSS, so we use JavaScript for it. - const main = this.renderRoot.querySelector("main"); - const header = this.renderRoot.querySelector("header"); - if (main !== null && header !== null) { - if (this.position.includes("up")) { - main.style.setProperty( - "margin-bottom", - `${header.getBoundingClientRect().height}px`, - ); - } - - if (this.position.includes("down")) { - main.style.setProperty( - "margin-top", - `${header.getBoundingClientRect().height}px`, - ); - } - } - } - render() { // The element doesn't yet have our config, don't render it. if (this.config === null) { From bfde1ec1c6de6eb4c49fe65cceca36c02a65f97b Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 28 Jan 2025 13:02:51 +0100 Subject: [PATCH 16/16] More CSS tricks --- src/flyout.css | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/flyout.css b/src/flyout.css index 8d0e4c41..ee0d86f9 100644 --- a/src/flyout.css +++ b/src/flyout.css @@ -13,13 +13,17 @@ .container { position: fixed; max-width: var(--readthedocs-flyout-max-width, 25em); - width: auto; height: auto; + width: auto; max-height: calc(100% - 100px); overflow-y: auto; line-height: var(--addons-flyout-line-height); } +.container.closed { + height: 2.5rem; +} + .container.bottom-right:not(.inline) { right: 20px; bottom: 50px; @@ -52,6 +56,16 @@ overflow: visible; } +.container.up.inline main { + top: unset; + bottom: 2.5rem; +} + +.container.down.inline main { + top: 2.5rem; + bottom: unset; +} + :host > div { font-family: var( --readthedocs-flyout-font-family, @@ -137,6 +151,9 @@ main { /* Use full width minus 1em padding added on left and right in `.container.inline main` */ width: calc(100% - 2em); + + position: absolute; + margin-top: 0; } main.closed,