如何在2个flex样式行之间添加元素,并根据新元素高度使下面的行向下移动?

时间:2015-07-13 15:48:16

标签: javascript css grid flexbox

请看一下这个基本示例:

http://tympanus.net/Blueprints/ResponsiveFullWidthGrid/

现在想象一下,通过点击一个猫盒,我需要(特别是在中小屏幕上)在点击的猫行下面添加一个100%宽度的文本框(比如被点击的猫的描述) 。该文本框应该按下其余行。

我是css / js / frontend开发人员,但我从未遇到过这样的问题。这也是我第一次使用flexbox布局。使用固定布局会非常简单,但在这种情况下,我无法找到一个好方法。例如,要解决的问题之一是:我应该把盒子放在哪里(相对于点击的盒子?),我应该根据每行的当前项目还是通过javascript更改位置,或者是否有更聪明的CSS方式?“ p>

任何想法都表示赞赏。

1 个答案:

答案 0 :(得分:0)

这是一个有趣的挑战:)

知道放置区域的位置(我称之为infoBox)的唯一方法是识别下一行的第一个节点,然后将其插入到它之前。如果最后一行没有节点,我们可以将其附加到ul的末尾。

我还添加了一个window.resize事件处理程序,它将关闭infoBox,因此它不会破坏响应式布局和关闭按钮。

工作示例 - fiddle

HTML是来自codrop文章的复制粘贴。

JS

var rfgrid = document.querySelector('.cbp-rfgrid');
var items = Array.from(document.querySelectorAll('.cbp-rfgrid > li'));

/** Create infoBox **/
var infoBox = document.createElement('div');
infoBox.classList.add('infoBox');
infoBox.innerHTML = '<div class="close">X</div><div class="content"></div>';
infoBoxClose = infoBox.querySelector('.close');
infoBoxContent = infoBox.querySelector('.content');

/** add close button functionality **/
infoBoxClose.addEventListener('click', function() {
    rfgrid.removeChild(infoBox);
});

/** remove infoBox on resize to maintain layout flow **/
window.addEventListener('resize', function() {
    rfgrid.removeChild(infoBox);
});

items.forEach(function (item) {
    item.addEventListener('click', function (event) {
        event.preventDefault();
        var insertReference = findReference(this); // get refence to next line 1st node
        infoBoxContent.innerHTML = items.indexOf(this); // example of changing infoBox content

        if(insertReference) {
            rfgrid.insertBefore(infoBox, insertReference); // insert infoBox before the reference
        } else {
            rfgrid.appendChild(infoBox); // insert infoBox as last child
        };
    });
});

/** find reference to 1st item of next line or null if last line **/
function findReference(currentNode) {
    var originalTop = currentNode.offsetTop; // get the clicked item offsetTop

    do {
        currentNode = currentNode.nextSibling; // get next sibling
    } while (currentNode !== null && (currentNode.nodeType !== 1 || currentNode.offsetTop === originalTop)); // keep iterating until null (last line) or a node with a different offsetTop (next line)

    return currentNode;
}

CSS(除了原版)

.infoBox {
    position: relative;
    width: 100%;
    height: 200px;
    padding: 20px 0 0 0;
    clear: both;
    background: paleturquoise;
}

.infoBox > .close {
    position: absolute;
    top: 5px;
    right: 5px;
    cursor: pointer;
}