英文:
Absolute positioned div inside scroll container is positioned relative only to unscrolled position
问题
I am creating a table of contents sidebar where I want the text to be truncated normally, but expand on hover to show the full text of the list item. The TOC should also be scrollable separate from the main content (e.g., TOC is always visible and the "main" content scrolls on its own).
Using some wrappers and position: absolute
I can make the text pop out of the TOC container. However, if the ancestor element of the list item is scrolled at all, then the element with absolute positioning shows up in the location as if the parent was not scrolled.
I tried a combination of different modifications such as adding top: 0
on the element or on the immediate parent, making any/all ancestors either absolute
/ relative
. Resulting in one these outcomes:
- Nothing changes
- The element which should pop up no longer breaks out / visible
x
but is in the right position - The element I want to break out goes to the top of the parent container.
I am using set of nested grids, but if there is a different way to create the same containers, I would consider it.
英文:
I am creating a table of contents sidebar where I want the text to be truncated normally, but expand on hover to show the full text of the list item. The TOC should also be scrollable separate from the main content (e.g., TOC is always visible and the "main" content scrolls on its own).
Using some wrappers and position: absolute
I can make the text pop out of the TOC container. However, if the ancestor element of the list item is scrolled at all, then the element with absolute positioning shows up in the location as if the parent was not scrolled.
I tried a combination of different modifications such as adding top: 0
on the element or on the immediate parent, making any/all ancestors either absolute
/ relative
. Resulting in one these outcomes:
- Nothing changes
- The element which should pop up no longer breaks out / visible
x
but is in the right position - The element I want to break out goes to the top of the parent container.
I am using set of nested grids, but if there is a different way to create the same containers, I would consider it.
Here is a screenshot without scrolling, it accomplishes the goal:
However, when the element is scrolled, you can see the absolute position element seems to not take into consideration that the parent scrolled.
See code insert below. I created the break out affect on li:hover
and on #testcase
.
I am currently using the title
attribute as a fallback since that will always show ontop, but I cannot style or control the timing, so the breakout effect in the right position would still be better.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
/**reset.css*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
/** layout.css */
#app {
margin: 0;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'header'
'content'
'footer';
}
#content {
grid-area: content;
overflow: auto;
}
#content {
display: grid;
grid-template-columns: 15vw 1fr;
grid-template-rows: 1fr;
grid-template-rows: 100%;
grid-column-gap: 2vw;
}
main {
max-width: 900px;
margin-right: 5vw;
}
#toc {
margin-left: 5px;
margin-right: 5px;
align-self: start;
height: 100%;
}
#toc{
display: grid;
grid-template-rows: auto ;
}
#toc > ul {
overflow:hidden;
overflow-y: auto;
/* height: 100%; */
}
#toc:not(:hover) ul::-webkit-scrollbar{
visibility: hidden;
}
#toc > ul {
margin-bottom: 0;
margin-top:0;
}
#toc h3{
padding-top: 1em;
padding-bottom: 1em;
}
header, footer{
background-color: rgb(241, 248, 255);
}
#toc{
background-color: rgb(246, 242, 255);
}
#toc ul{
outline: 1px solid pink;
}
main{
background-color: rgb(238, 255, 250);
}
/* toc.css */
#toc {
line-height: 1.3;
}
#toc a::before{
font-family: 'Noto Emoji', serif;
}
#toc li .toc-item-wrapper {
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width:100%;
height:1.3em;
}
/* #toc li:has(a[data-indent-section="true"])::before{ */
#toc li .toc-item-wrapper:has(a[data-indent-section="true"])::before{
content: '↳';
margin-left: .3em;
margin-right: .1em;
}
/***/
#toc li:hover .toc-item-wrapper,
.toc-item-wrapper:has(a#testcase) {
overflow: visible;
}
#toc li:hover a,
a#testcase
{
position:absolute;
overflow: visible;
outline: 3px solid #000;
background-color: var(--jelly-25);
padding-right:.5em;
}
#toc li{
height:1.3em;
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>TEST</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Emoji" type="text/css" media="all" />
<link rel="stylesheet" href="css/reset.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/layout.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/toc.css" type="text/css" media="all" />
</head>
<body id="app">
<header>
<div>Header, nav, etc.</div>
</header>
<div id="content">
<aside id="toc">
<h3>Your Progress</h3>
<ul>
<li>
<div class="toc-item-wrapper">
<a href="#" title="AAAAAAA">AAAAAAA 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="BBBBBBB">BBBBBBB 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" data-indent-section="true" title="CCCCCCC">CCCCCCC 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a id="testcase" href="#" data-indent-section="true" title="DDDDDDD">DDDDDDD 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="EEEEEEE">EEEEEEE 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="FFFFFFF">FFFFFFF 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="GGGGGGG">GGGGGGG 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="HHHHHHH">HHHHHHH 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="IIIIIII">IIIIIII 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="JJJJJJJ">JJJJJJJ 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="KKKKKKK">KKKKKKK 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="LLLLLLL">LLLLLLL 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="MMMMMMM">MMMMMMM 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="NNNNNNN">NNNNNNN 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="OOOOOOO">OOOOOOO 0123456789 0123456789</a>
</div>
</li>
</ul>
</aside>
<main>
<section>Main Content</section>
<section>More Content</section>
</main>
</div>
<footer>Site Footer</footer>
</body>
</html>
<!-- end snippet -->
答案1
得分: 3
你可以创建一个自定义的工具提示,它不在带有 overflow: auto;
和 position: fixed;
的块内,并且需要在 onscroll
事件之后更改其位置。
或者你可以使用工具提示库,比如 Tippy.js:
例如,像这样的代码:
document.querySelectorAll('.toc-item-wrapper a').forEach(el => {
tippy(el, {
content: el.textContent,
placement: 'top-start',
arrow: false,
maxWidth: 'none',
offset: [0, 0],
duration: [0, 0],
});
});
英文:
You can create a custom tooltip that is not in a block with overflow: auto;
and has position: fixed;
. Then you need to change its position after the onscroll
event.
Or you can use a tooltip library such as Tippy.js:
For example, something like this:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelectorAll('.toc-item-wrapper a').forEach(el => {
tippy(el, {
content: el.textContent,
placement: 'top-start',
arrow: false,
maxWidth: 'none',
offset: [0, 0],
duration: [0, 0],
});
});
<!-- language: lang-css -->
/**reset.css*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
/** layout.css */
#app {
margin: 0;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'header'
'content'
'footer';
}
#content {
grid-area: content;
overflow: auto;
}
#content {
display: grid;
grid-template-columns: 15vw 1fr;
grid-template-rows: 1fr;
grid-template-rows: 100%;
grid-column-gap: 2vw;
}
main {
max-width: 900px;
margin-right: 5vw;
}
#toc {
margin-left: 5px;
margin-right: 5px;
align-self: start;
height: 100%;
}
#toc{
display: grid;
grid-template-rows: auto ;
}
#toc > ul {
overflow:hidden;
overflow-y: auto;
/* height: 100%; */
}
#toc:not(:hover) ul::-webkit-scrollbar{
visibility: hidden;
}
#toc > ul {
margin-bottom: 0;
margin-top:0;
}
#toc h3{
padding-top: 1em;
padding-bottom: 1em;
}
header, footer{
background-color: rgb(241, 248, 255);
}
#toc{
background-color: rgb(246, 242, 255);
}
#toc ul{
outline: 1px solid pink;
}
main{
background-color: rgb(238, 255, 250);
}
/* toc.css */
#toc {
line-height: 1.3;
}
#toc a::before{
font-family: 'Noto Emoji', serif;
}
#toc li .toc-item-wrapper {
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width:100%;
height:1.3em;
}
/* #toc li:has(a[data-indent-section="true"])::before{ */
#toc li .toc-item-wrapper:has(a[data-indent-section="true"])::before{
content: '↳';
margin-left: .3em;
margin-right: .1em;
}
/***/
#toc li{
height:1.3em;
}
#toc li a{
color:blue;
}
/* tippy */
.tippy-box{
transform:translateY(100%);
background:none;
color:inherit;
outline: 3px solid #000;
background-color: var(--jelly-25);
padding:0;
font:inherit;
}
.tippy-content{
padding:0;
background-color:rgb(246, 242, 255);
line-height:inherit;
color:blue;
text-decoration:underline;
}
<!-- language: lang-html -->
<body id="app">
<header>
<div>Header, nav, etc.</div>
</header>
<div id="content">
<aside id="toc">
<h3>Your Progress</h3>
<ul>
<li>
<div class="toc-item-wrapper">
<a href="#" title="AAAAAAA">AAAAAAA 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="BBBBBBB">BBBBBBB 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" data-indent-section="true" title="CCCCCCC">CCCCCCC 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a id="testcase" href="#" data-indent-section="true" title="DDDDDDD">DDDDDDD 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="EEEEEEE">EEEEEEE 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="FFFFFFF">FFFFFFF 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="GGGGGGG">GGGGGGG 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="HHHHHHH">HHHHHHH 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="IIIIIII">IIIIIII 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="JJJJJJJ">JJJJJJJ 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="KKKKKKK">KKKKKKK 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="LLLLLLL">LLLLLLL 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="MMMMMMM">MMMMMMM 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="NNNNNNN">NNNNNNN 0123456789 0123456789</a>
</div>
</li>
<li>
<div class="toc-item-wrapper">
<a href="#" title="OOOOOOO">OOOOOOO 0123456789 0123456789</a>
</div>
</li>
</ul>
</aside>
<main>
<section>Main Content</section>
<section>More Content</section>
</main>
</div>
<footer>Site Footer</footer>
</body>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论