BPL*_*BPL 6 html javascript css
我正在学习一些 CSS,今天我发现自己想要实现一个类似的上下文菜单(当您点击 youtube 卡片上的垂直省略号时显示的菜单),但我的尝试没有成功很远:D。这是我所拥有的:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.container {
display: inline-block;
position: relative;
}
.dropdown {
position: absolute;
right: 1rem;
top: 1rem;
}
.dropdown-opener {
cursor: pointer;
user-select: none;
position: absolute;
right: 0;
}
.dropdown .dropdown-toggle,
.dropdown .dropdown-menu {
display: none;
style-type: none;
}
.dropdown .dropdown-toggle:checked+ul {
display: block;
}
.style-scope .menu-renderer {
--layout-inline_-_display: inline-flex;
--icon-button-icon-height: 24px;
--icon-button-icon-width: 24px;
--spec-icon-active-other: #606060;
--spec-icon-inactive: #909090;
--spec-text-disabled: #909090;
--spec-text-secondary: #606060;
align-items: var(--layout-center-center_-_align-items);
color: var(--menu-renderer-button-color, var(--spec-icon-inactive));
cursor: pointer;
display: var(--layout-inline_-_display);
fill: var(--iron-icon-fill-color, currentcolor);
width: var(--icon-button-icon-width, 100%);
background: transparent;
}
</style>
</head>
<body>
<div class="container">
<img alt="sample" src="https://via.placeholder.com/200x200">
<nav class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener1">...</label>
<input class="dropdown-toggle" id="menu-opener1" type="checkbox">
<ul class="dropdown-menu">
<li>Foo1</li>
<li>Bar1</li>
<li>Baz1</li>
</ul>
</nav>
</div>
<div class="container">
<img alt="sample" src="https://via.placeholder.com/200x200">
<nav class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener1">...</label>
<input class="dropdown-toggle" id="menu-opener1" type="checkbox">
<ul class="dropdown-menu">
<li>Foo2</li>
<li>Bar2</li>
<li>Baz2</li>
</ul>
</nav>
</div>
<div class="container">
<img alt="sample" src="https://via.placeholder.com/200x200">
<nav class="dropdown layer--topright">
<icon-button id="button" class="dropdown-opener dropdown-trigger style-scope menu-renderer">
<button id="button" class="style-scope icon-button" aria-label="Action menu">
<icon class="style-scope menu-renderer">
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope icon" style="pointer-events: none; display: block; width: 100%; height: 100%;">
<g class="style-scope icon">
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" class="style-scope icon"></path>
</g>
</svg>
</icon>
</button>
</icon-button>
<input class="dropdown-toggle" id="menu-opener2" type="checkbox">
<ul class="dropdown-menu">
<li>Foo3</li>
<li>Bar3</li>
<li>Baz3</li>
</ul>
</nav>
</div>
</body>
</html>Run Code Online (Sandbox Code Playgroud)
如您所见,代码很脏且损坏……但是我的尝试存在重大问题,我不知道如何解决:
因此,如果您能解释如何解决这些问题,以便从我的尝试中获得一些有用的东西,那就太棒了。
或者,如果我的方法完全错误,无法使用并准备扔进垃圾箱……您能解释一下实现我的目标的最佳方法吗?
提前致谢。
单击溢出菜单按钮时错位的上下文菜单。上下文菜单实际上并没有放错位置。元素中的for属性<label>引用了错误的上下文菜单。例如,for你的价值<label>元素在第一.container具有的价值menu-opener1,但for在价值<label>的元素第二个 .container具有完全相同的值。单击任一标签都会打开第一个容器中的下拉菜单,因为这两个标签都会导致选中第一个容器上的隐藏复选框。
我们可以做什么?只需更改该id值,以便每个下拉菜单都有一个唯一的 id 值。然后,将该 id 值用于元素for内的值<label>。
要将li元素的公告隐藏在 a 中ul,您必须list-style-type: none在 CSS上使用而不是 style-type: none.
这是一个非常主观的问题。一种设计在一个人看来很干净,但在其他人看来却是不干净的。尽管如此,我试图实现我想看到的。以下是您可以更改以改进设计方面的一些内容。
li元素之间添加空格。在这里,我使用了line-height. 您还可以在每个元素上使用padding或。marginlibox-shadow以显示高程。Google 的 Material Design 建议使用这种技术来显示元素的 z 位置更高。visibility和display)。在这里,我选择了使用transform: scale和opacity过渡。从语义上讲,您的 HTML 标记不正确。
<nav>(导航)元素用于页面间导航。在这里,您可能应该使用<menu>element 代替。但是,由于它仍处于实验阶段,我选择使用<section>.<icon-button>和<icon>)。尝试在此处咨询有效的 HTML 标签,在此处咨询有效的 SVG 标签。.container一项有一个按钮,可以检查隐藏的复选框。但是,该<button>元素不适用于<label>element。所以,试着让<label>元素在视觉上看起来像一个按钮。您可以使用:active和:hoverCSS 伪选择器分别在按下和悬停按钮时更改按钮样式。此外,这减少了嵌套。.container包含整个页面,所以我选择使用类名.box而不是.container.这是可运行的代码段。
* {
font-family: Helvetica;
box-sizing: border-box;
}
.box {
display: inline-block;
position: relative;
}
.dropdown {
position: absolute;
right: 0;
top: 8px;
}
.dropdown-opener {
cursor: pointer;
user-select: none;
position: absolute;
width: 24px;
height: 24px;
background: url('https://i.imgur.com/Qt3Qwgp.png');
background-repeat: no-repeat;
background-position: right;
right: 0;
}
.dropdown .dropdown-toggle {
display: none;
}
.dropdown .dropdown-menu {
list-style-type: none;
transform: scale(0);
opacity: 0;
transition:
transform 0.25s ease,
opacity 0.25s ease;
position: absolute;
top: 1.5em;
right: 10px;
line-height: 1.75em;
background: white;
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.5);
border-radius: 5px;
padding: 20px;
margin: 0;
transform-origin: top right;
}
.dropdown .dropdown-toggle:checked + ul {
transform: scale(1);
opacity: 1;
}
.dropdown-opener-button {
position: absolute;
width: 24px;
height: 24px;
right: 8px;
top: 0;
}
.icon-button {
padding: 0;
border: 0;
border-radius: 5px;
cursor: pointer;
transition:
box-shadow .25s ease,
background .25s ease,
transform .25s ease;
background: #ffffffdd;
}
.icon-button:hover {
box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.35);
}
.icon-button:active {
background: #ffffff77;
transform: scale(0.9);
}
.icon-button ~ .dropdown-menu {
top: 1.75em;
}Run Code Online (Sandbox Code Playgroud)
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener1"></label>
<input class="dropdown-toggle" id="menu-opener1" type="checkbox">
<ul class="dropdown-menu">
<li>Foo1</li>
<li>Bar1</li>
<li>Baz1</li>
</ul>
</section>
</div>
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener2"></label>
<input class="dropdown-toggle" id="menu-opener2" type="checkbox">
<ul class="dropdown-menu">
<li>Foo2</li>
<li>Bar2</li>
<li>Baz2</li>
</ul>
</section>
</div>
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener-button icon-button" for="menu-opener3">
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope icon">
<g class="style-scope icon">
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" class="style-scope icon"></path>
</g>
</svg>
</label>
<input class="dropdown-toggle" id="menu-opener3" type="checkbox">
<ul class="dropdown-menu">
<li>Foo3</li>
<li>Bar3</li>
<li>Baz3</li>
</ul>
</section>
</div>Run Code Online (Sandbox Code Playgroud)
对 OP 的含义没有清晰的理解,即在用鼠标悬停时使菜单项更改状态的难度有多大,我决定在悬停时创建一个效果,并在单击时创建一个不同的效果(涟漪)该<li>元素。我推荐阅读这篇关于创建涟漪效应的文章。
此外,根据要求,添加了在菜单框外单击时隐藏菜单的功能。这是可运行的代码段。
// Closing menu on outside click
const outsideClickListener = event => {
let checkedToggle = document.querySelector('.dropdown-toggle:checked')
let openedMenu = document.querySelector('.dropdown-toggle:checked + .dropdown-menu')
// If click is performed on checkbox (through label), do nothing
if (event.target.classList.contains('dropdown-toggle')) {
return
}
// If click is performed on label, uncheck all other dropdown-toggle
if (event.target.classList.contains('dropdown-opener') ||
event.target.classList.contains('dropdown-opener-button')) {
let forId = event.target.getAttribute('for')
document.querySelectorAll('.dropdown-toggle').forEach(toggle => {
if (forId !== toggle.getAttribute('id'))
toggle.checked = false
})
return
}
// If click is performed outside opened menu
if (openedMenu && !openedMenu.contains(event.target)) {
checkedToggle.checked = false
}
}
document.addEventListener('click', outsideClickListener)
// Ripple effect on li elements
const createRipple = event => {
let li = event.target
let liBox = li.getBoundingClientRect()
let x = event.pageX - liBox.left
let y = event.pageY - liBox.top
let animDuration = 350
let animationStart, animationFrame
let animationStep = timestamp => {
if (!animationStart) animationStart = timestamp
let frame = timestamp - animationStart
if (frame < animDuration) {
let easing = (frame / animDuration) * (2 - (frame / animDuration))
let circle = `circle at ${x}px ${y}px`
let color = `rgba(0, 0, 0, ${0.2 * (1 - easing)})`
let stop = `${100 * easing}%`
li.style.backgroundImage = `radial-gradient(${circle}, ${color} ${stop}, transparent ${stop})`
animationFrame = window.requestAnimationFrame(animationStep)
}
else {
li.style.backgroundImage = ''
window.cancelAnimationFrame(animationStep)
}
}
animationFrame = window.requestAnimationFrame(animationStep)
}
const listItems = document.querySelectorAll('li')
listItems.forEach(li => {
li.addEventListener('click', createRipple)
})Run Code Online (Sandbox Code Playgroud)
* {
font-family: Helvetica;
box-sizing: border-box;
}
.box {
display: inline-block;
position: relative;
}
.dropdown {
position: absolute;
right: 0;
top: 8px;
}
.dropdown-opener {
cursor: pointer;
user-select: none;
position: absolute;
width: 24px;
height: 24px;
background: url('https://i.imgur.com/Qt3Qwgp.png');
background-repeat: no-repeat;
background-position: right;
right: 0;
}
.dropdown .dropdown-toggle {
display: none;
}
.dropdown .dropdown-menu {
list-style-type: none;
transform: scale(0);
opacity: 0;
transition:
transform 0.25s ease,
opacity 0.25s ease;
position: absolute;
top: 1.5em;
right: 10px;
background: white;
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.5);
border-radius: 5px;
margin: 0;
transform-origin: top right;
padding: 7.5px 0 7.5px 0;
}
.dropdown .dropdown-toggle:checked + ul {
transform: scale(1);
opacity: 1;
}
.dropdown-menu li {
padding: 7.5px;
padding-left: 25px;
cursor: pointer;
transition: background .15s ease;
}
.dropdown-menu li:hover {
background: #00000012;
}
.dropdown-opener-button {
position: absolute;
width: 24px;
height: 24px;
right: 8px;
top: 0;
}
.dropdown-opener-button svg {
pointer-events: none;
}
.icon-button {
padding: 0;
border: 0;
border-radius: 5px;
cursor: pointer;
transition:
box-shadow .25s ease,
background .25s ease,
transform .25s ease;
background: #ffffffdd;
}
.icon-button:hover {
box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.35);
}
.icon-button:active {
background: #ffffffaa;
box-shadow: 0px 0px 4px 0px rgba(0,0,0,0.35);
transform: scale(0.9);
}
.icon-button ~ .dropdown-menu {
top: 1.75em;
}Run Code Online (Sandbox Code Playgroud)
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener1"></label>
<input class="dropdown-toggle" id="menu-opener1" type="checkbox">
<ul class="dropdown-menu">
<li>Foo1</li>
<li>Bar1</li>
<li>Baz1</li>
</ul>
</section>
</div>
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener" for="menu-opener2"></label>
<input class="dropdown-toggle" id="menu-opener2" type="checkbox">
<ul class="dropdown-menu">
<li>Foo2</li>
<li>Bar2</li>
<li>Baz2</li>
</ul>
</section>
</div>
<div class="box">
<img alt="sample" src="https://via.placeholder.com/200x200">
<section class="dropdown layer--topright">
<label class="dropdown-opener-button icon-button" for="menu-opener3">
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope icon">
<g class="style-scope icon">
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" class="style-scope icon"></path>
</g>
</svg>
</label>
<input class="dropdown-toggle" id="menu-opener3" type="checkbox">
<ul class="dropdown-menu">
<li>Foo3</li>
<li>Bar3</li>
<li>Baz3</li>
</ul>
</section>
</div>Run Code Online (Sandbox Code Playgroud)