>我在 CSS flex 容器中有一组可扩展的div。
代码笔 - https://codepen.io/vijayvmenon/pen/bGNRwvd
.CSS:
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
当我单击任何div 时,行中的其他div 也会展开。如何通过仅展开我单击的div 而不展开行中的其他div 来解决此问题?
我正在使用 flex 容器,因为我正在构建一个响应式页面,并且还有更多组件,此处未包含。可以使用柔性/网格容器吗?请让我知道。 我可以包装div并使其响应的任何其他解决方案都应该没问题。
我创建了一个类似的问题,我正在使用聚合物框架 - CSS 网格容器内的可折叠div 扩展整个宽度
由于我在这里没有得到任何帮助,所以想到在Vanilla Javascript中创建一个。请帮忙。
注意:我事先不知道实际的项目数,它是在聚合物库中使用"dom-repeat"渲染的。所以我只能有一个容器div 来包含完整的项目集。我不能为每列项目附上div(除非有办法做到这一点(
这是下面的代码(香草JS,因为我不使用聚合物(。它是响应式的,会根据您的item
宽度调整列的数量(我假设您将使用media-query
进行更改(。这个想法是:
- 通过创建虚拟项来测量您在 CSS 中指定的
item
宽度 - 根据测量的
item
宽度调整所需的列数。有必要将项目包装在列中,因为不可能通过将所有内容包装在一个 flex 容器中来执行您想要的操作。 - 使用原版JS动态创建元素(在您的情况下使用聚合物(
- 逐个将项目添加到列中
- 点击的逻辑仍然和你的 一样
以下是完整的工作示例:
let container = document.querySelector('.container')
let columnAmount = (() => {
let containerWidth = parseInt(getComputedStyle(container).width)
let dummyItem = document.createElement('div')
let itemWidth
dummyItem.classList.add('item')
container.appendChild(dummyItem)
itemWidth = parseInt(getComputedStyle(dummyItem).width)
dummyItem.remove()
return Math.floor(containerWidth / itemWidth)
})()
let newColumns = []
for (let i = 0; i < columnAmount; i++) {
newColumns.push(document.createElement('div'))
newColumns[i].classList.add('item')
container.appendChild(newColumns[i])
}
let childAmount = 11 // Change this to your needs
let newChild
let newCollapsibleButton
let newContent
let newContentParagraph
for (let i = 0; i < childAmount; i++) {
newChild = document.createElement('div')
newCollapsibleButton = document.createElement('button')
newContent = document.createElement('div')
newContentParagraph = document.createElement('p')
newChild.classList.add('item--inner')
newCollapsibleButton.classList.add('collapsible')
newContent.classList.add('content')
newCollapsibleButton.appendChild(document.createTextNode(`Open Section ${i + 1}`))
newContentParagraph.appendChild(document.createTextNode(`Section ${i + 1} Details`))
newContent.appendChild(newContentParagraph)
newChild.appendChild(newCollapsibleButton)
newChild.appendChild(newContent)
newColumns[i % columnAmount].appendChild(newChild)
}
let collapsibleButtons = document.querySelectorAll(".collapsible");
for (let i = 0; i < collapsibleButtons.length; i++) {
collapsibleButtons[i].addEventListener('click', function() {
let content = this.nextElementSibling;
this.classList.toggle("active");
content.style.maxHeight = content.style.maxHeight ? null : `${content.scrollHeight}px`
});
}
.container {
display:flex;
justify-content:space-between;
flex-wrap:wrap;
}
.item {
width: 30%;
}
.item--inner {
width: 100%;
}
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
<div class = "container">
</div>
请注意,它不处理页面大小调整,即项目将在页面加载时处于固定状态(必要时处理页面大小调整(。为方便起见,请调整此 JSFiddle 的屏幕大小:此处,看看它对不同屏幕尺寸的反应。在上面的代码段上运行只允许加载一列项目,我已经进行了调整,以便container
大小非常有限。item
具有item--inner
,并允许item
始终为容器尺寸的 30%。如果您不希望它始终是其容器大小的 30%,只需更正item
的 CSS 样式即可。为了更轻松地调整代码,请参阅此处的 JSFiddle:此处。
注意:如果您想查看两列版本和垂直堆叠版本,请将item
宽度更改回 400 像素。确保在页面加载之前调整屏幕大小。
好吧,这是我的解决方案...
它在每列上创建一个新的div,并分散其中的所有项目。 在窗口调整大小时,它会创建或多或少的列,以尊重响应情况
这是我的代码:
(function () {
const Container = document.querySelector('.container')
, All_item = [...document.querySelectorAll('.item')]
;
if ( All_item.length===0 ) return
const items_W = All_item[0].offsetWidth // get item width
, divGpr = document.createElement('div') // base col element
, flexCol = [] // array of ihm cols
;
divGpr.style.width = items_W+'px'; // perfect size
function SetNewCols() //
{
let nbCol = Math.max(1, Math.floor( Container.offsetWidth / items_W ) )
, len = flexCol.length;
if (nbCol===len) return // col unchanged
for(let k=0;k<nbCol;k++) // create new Col
{ flexCol.push( Container.appendChild(divGpr.cloneNode(true))) }
let k=0;
for(item of All_item)
{
flexCol[len+k].appendChild(item) // dispach item in new col
k = ++k % nbCol // future col of
}
for(i=0;i<len;i++)
{ Container.removeChild( flexCol.shift() ) } // remove old empty cols
if(k>0)
{ flexCol[( flexCol.length -1)].appendChild(item) }
}
SetNewCols(); // first Attempt
window.addEventListener('resize', SetNewCols);
document.querySelectorAll(".container button").forEach(Koll=>
{
Koll.onclick=e=>
{
let content = Koll.nextElementSibling;
content.style.maxHeight = Koll.classList.toggle("active")
? content.scrollHeight + "px"
: 0;
}
})
})();
.container {
display:flex;
justify-content:space-between;
flex-wrap:wrap;
}
.container .item {
width:400px;
}
.container .item > button {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.container .item .content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
<div class="container">
<div class="item">
<button>Open Section 1</button>
<div class="content">
<p>Section 1 details</p>
</div>
</div>
<div class="item">
<button>Open Section 2</button>
<div class="content">
<p>Section 2 details</p>
</div>
</div>
<div class="item">
<button>Open Section 3</button>
<div class="content">
<p>Section 3 details</p>
</div>
</div>
<div class="item">
<button>Open Section 4</button>
<div class="content">
<p>Section 4 details</p>
</div>
</div>
<div class="item">
<button>Open Section 5</button>
<div class="content">
<p>Section 5 details</p>
</div>
</div>
<div class="item">
<button>Open Section 6</button>
<div class="content">
<p>Section 6 details</p>
</div>
</div>
</div>
你可以做的是创建一个类似列的结构,将所有列元素分组到一个带有类项的div 中:
<div class="container">
<div class="item">
<div class="item">
<button class="collapsible">Open Section 1</button>
<div class="content">
<p>Section 1 details</p>
</div>
</div>
<div class="item">
<button class="collapsible">Open Section 4</button>
<div class="content">
<p>Section 4 details</p>
</div>
</div>
</div>
...
</div>
我把修改后的代码笔留给你!希望这就是你想做的!
在我的方法中,我将使用$(document).on('click', '.collapsible', function () {});
let $collBtn = '.item > .collapsible'; // all collapse
$(document).on('click', '.collapsible', function (e) {
e.preventDefault();
$($collBtn).removeClass('active');
$(this).addClass('active');
});
一旦.collabsible
有一个类active
它将像 togleClass(( 一样扩展元素。根据我的经验,当我有多个按钮并使用$(document).on('click', '.item', function () {})
这相当于在相同的元素中找到一个类&&按钮。希望这会有所帮助。:)
@Vijay:- 这不是问题,而是正常行为。当您单击任何div 时,该行中的其他div 不会展开,但内容会取代它的位置,并将其他元素推到该行下方,以便为内容显示提供空间。您只能使用相同的 HTML 结构的相对逻辑和绝对逻辑。
*{
box-sizing:border-box;
}
.item{
position:relative;
}
.content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
position:absolute;
top:100%;
left:0;
right:0;
}