弹性容器中的可折叠 div 也会打开其他 div



>我在 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;
}

最新更新