仅当overflow: auto块溢出时,在内容和滚动块之间添加缩进(margin|padding)



我有一个未知元素数量的列表

我需要在滚动和内容之间应用填充只有当列表溢出

<div class="list">
<div class="item">1</div>         
<div class="item">many items or 1</div>          
</div>
css
.list {
padding-right: 10px // i need apply this only if scroll apeared
max-height: 40px
overflow: auto
}

我不确定这是否可能与CSS,但你可以用JS,检查它像element.scrollHeight > element.clientHeight

例如:

const listElement = document.querySelector('.list');
//OR window.addEventListener('resize', () => applyStylesToList());
new ResizeObserver(() => applyStylesToList).observe(listElement);
applyStylesToList();
function applyStylesToList() {
const hasScroll = isScrollbarVisible(listElement);
listElement.style.paddingRight = hasScroll ? '10px' : '0';
}
function isScrollbarVisible(element) {
return element.scrollHeight > element.clientHeight;
}
.list {
max-height: 40px;
overflow: scroll;
}
<div class="list">
<div class="item">item</div>   
<div class="item">item</div>
<div class="item">item</div>
</div>

我能够得到填充显示后,第三个div被输入到您的列表。它确实需要一些普通的JavaScript来实现这种方式。希望这对你有帮助!

let list = document.querySelector(".list");
function moreThan() {
if (list.childElementCount >= 3) {
list.style.paddingRight = "10px";
}
}
list.addEventListener("overflow", moreThan());
.list {
/* padding-right: 10px; */
max-height: 40px;
overflow: auto;
}
<div class="list">
<div class="item">1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
<div class="item">many items or 1</div>
</div>

基于Telman的回答,我构建了这个List react组件

list.tsx

import s from './list.module.scss'
import { FC, useRef } from 'react'
import { useIsOverflowed } from '../../../hooks/dom/use-is-overflowed'
type Props = {
variant?: 'dark' | 'white'
className?: string
scrollPadding?: number
}

export const List: FC<Props> = ({ scrollPadding = 13, variant = 'white', 
className, children }) => {
const ref = useRef<HTMLDivElement>(null)
const hasScroll = useIsOverflowed(ref)
return (
<div
ref={ref}
style={{
paddingRight: hasScroll ? scrollPadding : 0
}}
className={`${s.wrapper} ${className} ${s[variant]}`}
>
{children}
</div>
)}

use-is-overflowed.ts

import { RefObject, useEffect, useState } from 'react'
export const useIsOverflowed = <T extends HTMLElement>(ref: RefObject<T>) 
=> {
const [isOverflowed, setIsOverflowed] = useState(false)
useEffect(() => {
const resizeObserver = new ResizeObserver(([entry]) => {
setIsOverflowed(entry.target.scrollHeight > entry.target.clientHeight)
})
resizeObserver.observe(ref.current as Element)
return () => resizeObserver.disconnect()
}, [])
return isOverflowed  }