这是一个简单的网格:https://codepen.io/ChucKN0risK/pen/zaWQOm
HTML:
<div class="card-wrapper">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="space-filler">Space filler</div>
</div>
CSS:
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.card-wrapper {
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
width: 100%;
height: 100%;
}
.card {
background-color: royalblue;
}
.space-filler {
display: flex;
align-items: center;
justify-content: center;
background-color: tomato;
}
我希望我的“空格填充”项填充网格的剩余空间,但仅当最后一行具有多个网格项时才填充。
这有可能吗?
预先感谢,祝您愉快
答案 0 :(得分:0)
我确实设法使用JS创建了自己的解决方案
代码如下:https://codepen.io/ChucKN0risK/pen/zaWQOm
HTML:
<div class="card-wrapper js-grid-wrapper">
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="card js-grid-el"></div>
<div class="space-filler is-hidden js-space-filler">Space filler</div>
</div>
<div class="element-adder">
<button class="js-add-el">+ Add element</button>
<button class="js-remove-el">- Remove element</button>
</div>
SCSS:
.card-wrapper {
position: relative;
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
width: 100%;
height: 100%;
}
.card {
background-color: royalblue;
}
.space-filler {
position: absolute;
bottom: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: tomato;
opacity: 0.8;
&.is-hidden {
display: none;
}
}
// -------------------------
// DEMO SPECIFIC STYLE
// -------------------------
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.element-adder {
display: flex;
flex-direction: column;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 2rem;
button {
flex: 1;
padding: 0.5rem;
border: none;
background-color: white;
cursor: pointer;
}
button + button {
margin-top: 0.5rem;
}
}
JS:
class SpaceFillerElement {
constructor() {
this._gridWrapper = document.querySelector('.js-grid-wrapper');
this.gridElClassname = 'js-grid-el';
this._el = this._gridWrapper.querySelector('.js-space-filler');
this._gridEl = document.querySelector(`.${this.gridElClassname}`);
this.gridElCount = this._gridWrapper.querySelectorAll(`.${this.gridElClassname}`).length;
this.gridColumnGap = getComputedStyle(this._gridWrapper).gridColumnGap;
this.events();
}
events() {
this.elementAdder();
this.observeGridWrapper();
this.displayEl();
this.setElDimensions();
// Since the user can resize
// the viewport we need to listen to the resize event so that
// the space filler element can adjust its dimensions.
window.addEventListener('resize', (e) => {
this.getColumnsCount();
this.setElDimensions();
this.displayEl();
});
}
getColumnsCount() {
const gridWrapperWidth = this._gridWrapper.clientWidth;
const gridElWidth = document.querySelector(`.${this.gridElClassname}`).clientWidth;
return Math.floor(gridWrapperWidth / gridElWidth);
}
displayEl() {
this.gridElCount = this._gridWrapper.querySelectorAll(`.${this.gridElClassname}`).length;
// If Number of elements / number of columns doesn't
// return an integer, it means that elements will be
// in the last row. And our space filler only displays
// itself during that condition.
if (this.gridElCount % this.getColumnsCount() !== 0) {
this._el.classList.remove('is-hidden');
} else {
this._el.classList.add('is-hidden');
}
}
setElDimensions() {
// 1) this._gridEl is the first child of our grid container. However,
// everytime we remove an item, we remove the first child which makes
// this._gridEl.clientHeight returns 0. That's why we must reassign
// its value to the new first child of our grid container.
this._gridEl = document.querySelector(`.${this.gridElClassname}`);
// 2) We must know the number of grid item to determine the
// number of child present in the last row.
this.gridElCount = this._gridWrapper.querySelectorAll(`.${this.gridElClassname}`).length;
const ElOnLastRow = this.gridElCount % this.getColumnsCount();
// 3) We set our space filler element's dimensions according to the
// space available in the last row.
const ElWidth = `calc(${this._gridEl.clientWidth}px * (${this.getColumnsCount()} - ${ElOnLastRow}) + (${this.gridColumnGap} * (${this.getColumnsCount()} - ${ElOnLastRow})))`;
const ElHeight = `calc(${this._gridEl.clientHeight}px + ${this.gridColumnGap})`;
this._el.style.height = ElHeight;
this._el.style.width = ElWidth;
}
// In my case, my grid item are dynamic and I need to adjust
// the space filler dimensions according to the number of
// grid items in the grid. I use the MutationObserver
// to call the this.displayEl() and this.setElDimensions() methods
// when child elements are added or removed from the grid.
observeGridWrapper() {
// Options for the observer (which mutations to observe)
const config = {
attributes: false,
childList: true,
subtree: true,
};
// Callback function to execute when mutations are observed
const callback = (mutationsList) => {
for(const mutation of mutationsList) {
if (mutation.type == 'childList') {
console.log('A child node has been added or removed.');
this.displayEl();
this.setElDimensions();
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(this._gridWrapper, config);
}
// I use this to simulate the adding or the removal of grid items.
elementAdder() {
document.querySelector('.js-add-el').addEventListener('click', () => {
// Create a new element
const newNode = document.createElement('div');
newNode.classList.add('card');
newNode.classList.add(this.gridElClassname);
// Insert the new node after the last element in the parent node
this._gridWrapper.append(newNode);
});
document.querySelector('.js-remove-el').addEventListener('click', (e) => {
this._gridWrapper.querySelector(`.${this.gridElClassname}`).remove();
});
}
}
new SpaceFillerElement();