Heim > Fragen und Antworten > Hauptteil
Ich habe ein Raster, das Quadrate in Zellen zeichnet. Es ermittelt die Anzahl der Zeilen und Spalten, zeichnet dann die Gitterzellen und prüft, ob in jeder Zelle ein Quadrat vorhanden sein sollte (gemäß der Anordnung), und zeichnet bei Bedarf ein Quadrat. Das HTML-Endergebnis sieht so aus: (Angenommen, ich habe 1 Zeile und 3 Spalten, nur 2 Zellen sollten Quadrate haben)
.row { display: flex; flex-wrap: wrap; flex: 10000 1 0%; } .column { display: flex; flex-wrap: wrap; max-width: 100px; min-width: 10px; padding: 4px; border: 1px solid grey; } .square { background-color: red; width: 100%; aspect-ratio: 1/1; border-radius: 5px; }
<div class="row"> <div class="column"> <div class="square"></div> </div> <div class="column"> <div class="square"></div> </div> <div class="column"></div> </div>
Die Zeilen nehmen die gesamte Breite des Bildschirms ein und die Spaltengrößen sollten zwischen allen Spalten gleich sein und sich je nach Anzahl der Spalten auf dem Bildschirm ändern (wenn ich beispielsweise 5 Spalten habe, sollten sie alle eine Breite von 100 haben). Pixel, aber wenn ich 1000 Spalten habe, sollten sie alle 10 Pixel breit sein).
Mein Problem ist, dass der Abstand und der Randradius nach einem bestimmten Haltepunkt in der Spaltengröße seltsam aussehen und ich ihre Werte ändern möchte, wenn ich diesen Haltepunkt erreiche. Ich kann keine @container-Abfragen verwenden, da diese noch nicht vollständig unterstützt werden.
Wenn es hilft, verwende ich Vue 2. Aber ich denke, eine CSS-Lösung wäre in diesem Fall besser.
P粉4278776762024-04-04 14:37:48
尝试解决所描述的问题:
我制作了一个小演示,帮助我更好地探索实现这种场景的条件。
.row
元素仍然是一个 Flexbox 容器,但它的 Flex 项目没有设置 border
,而是使用 outline
设置进行样式设置.
轮廓不占用空间,当与另一个元素生成的轮廓碰撞时,它会“崩溃”。
因此,为了确保布局不受样式奇怪的影响,在尝试展示 Flex 项目的边框时,此演示仅依赖于 2 个关键方面来渲染这些边框:
间隙
轮廓
大小,以覆盖之间留下的间隙
元素.row { gap: var(--col-gap); } .column { outline: var(--col-gap) solid gray; }
另外,红点被应用为具有 position:absolute
的 ::after
伪元素,再次确保没有任何内容影响网格布局:
.column.square::after { position: absolute; content: ''; background-color: red; width: 50%; aspect-ratio: 1/1; border-radius: 100%; top: 50%; left: 50%; transform: translate(-50%, -50%); }
从那里开始,我添加了一个带有 position:fixed
的“仪表板”,它保留在页面顶部并允许您控制:
display: none;
不会更改网格布局它完全取决于通过自定义变量 --col-width
设置的 .column
元素大小尽管我们努力最大限度地减少干扰,并采取了仅根据单元格的固定大小正确设置网格布局所需的所有步骤,但仍然存在一些问题渲染问题,有时某些线条的边框尺寸会出现常规的不匹配图案。 我应该说,我只在笔记本电脑显示屏上遇到问题,而不是在台式机显示器上,所以这是另一个因素。
我在演示中尝试了不同的参数并处理数字,同时也考虑到了差距。良好且安全的布局可以最大限度地减少潜在问题(例如,还可以提高边框尺寸)。
使用 Flex 布局我无法得到比这更进一步的结果。
const container = document.getElementById('container');
//draws the board
emptyElementAndFillWithColumns(container, 100);
//sets some columns randomly as .square
addRandomSquares(container);
//initializes the dashboard with the value coming from the css custom props
let columnsGap = parseInt(getCssCustomProp('col-gap'));
let columnsWidth = parseInt(getCssCustomProp('col-width'));
document.getElementById('gap').value = columnsGap;
document.getElementById('width').value = columnsWidth;
document.getElementById('width').dispatchEvent(new Event('change'));
document.getElementById('cols').value = Math.trunc(container.offsetWidth / (columnsWidth+columnsGap));
//input#width change event handler
document.getElementById('width')
.addEventListener('change', event => {
const width = parseInt(event.target.value);
const newCols = Math.trunc(container.offsetWidth / (width+columnsGap));
setCssCustomProp(container, 'col-width', `${width}px`);
document.getElementById('cols').value = newCols;
});
//input#cols change event handler
document.getElementById('cols')
.addEventListener('change', event => {
const cols = parseInt(event.target.value);
const newWidth = Math.trunc(container.offsetWidth / cols) - columnsGap;
setCssCustomProp(container, 'col-width', `${newWidth}px`);
document.getElementById('width').value = newWidth;
});
//input#gap change event handler
document.getElementById('gap')
.addEventListener('change', event => {
const gap = parseInt(event.target.value);
setCssCustomProp(container, 'col-gap', `${gap}px`);
columnsGap = gap;
});
//input#toggle-dots change event handler
document.getElementById('toggle-dots')
.addEventListener('change', event => {
container.classList.toggle('hide-dots');
});
//input#toggle-counters change event handler
document.getElementById('toggle-counters')
.addEventListener('change', event => {
container.classList.toggle('hide-counters');
});
//sets the --propName custom property at the style of target
function setCssCustomProp(target, propName, value){
target.style.setProperty(`--${propName}`, `${value}`);
}
//gets the --propName custom property value from the rule set on :root
function getCssCustomProp(propName){
const propValue =
getComputedStyle(document.documentElement).getPropertyValue(`--${propName}`);
return propValue;
}
//resets the container and appends a count number of columns
function emptyElementAndFillWithColumns(target, count){
for (i = 0; i <= count; i++) {
const column = document.createElement('div');
column.classList.add('column');
target.append(column);
}
}
//adds the square class to random .column elements in target
function addRandomSquares(target){
target.querySelectorAll('.column').forEach(column => {
if (Math.random() >= 0.5)
column.classList.add('square');
})
}
:root {
--col-width: 100px;
--col-gap: 1px;
}
*,
*::after,
*::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: sans-serif;
}
.row {
display: flex;
flex-wrap: wrap;
gap: var(--col-gap);
counter-reset: itemnr;
}
.column {
position: relative;
display: flex;
flex-wrap: wrap;
width: var(--col-width);
height: var(--col-width);
padding: 4px;
outline: var(--col-gap) solid gray;
}
.column.square::after {
position: absolute;
content: '';
background-color: red;
width: 50%;
aspect-ratio: 1/1;
border-radius: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.dashboard {
position: fixed;
right: 1rem;
top: 2rem;
border: solid darkgray;
padding: 1em;
z-index: 100;
background: gray;
color: white;
font-weight: 600;
font-size: 1.2rem;
opacity: .9;
}
.dashboard > *{
display: grid;
grid-template-columns: 1fr auto;
width: 100%;
gap: 1em;
}
.dashboard label{
}
.dashboard input[type="number"] {
width: 5em;
cursor: pointer;
}
.dashboard input[type="checkbox"] {
width: 1rem;
line-height: 1rem;
cursor: pointer;
}
#container.hide-dots .square::after{
display: none;
}
#container.hide-counters .column::before{
display: none;
}
small{
grid-column: 1 / -1;
font-size:.8rem;
text-align: center;
width: 100%;
margin-bottom: 1rem;
}
.column::before{
position: absolute;
counter-increment: itemnr;
content: counter(itemnr);
font-size: .8rem;
z-index: 10;
font-weight: 600;
}