Reduzieren Sie die Füllgröße, wenn das übergeordnete Element kleiner wird
P粉807397973
P粉807397973 2024-04-03 17:37:05
0
1
385

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粉807397973
P粉807397973

Antworte allen(1)
P粉427877676

尝试解决所描述的问题:

我制作了一个小演示,帮助我更好地探索实现这种场景的条件。

获取边框:弹性盒项目上的折叠等效项

.row 元素仍然是一个 Flexbox 容器,但它的 Flex 项目没有设置 border,而是使用 outline 设置进行样式设置.

轮廓不占用空间,当与另一个元素生成的轮廓碰撞时,它会“崩溃”。

因此,为了确保布局不受样式奇怪的影响,在尝试展示 Flex 项目的边框时,此演示仅依赖于 2 个关键方面来渲染这些边框:

  • 设置弹性项目之间的间隙
  • 设置轮廓大小,以覆盖之间留下的间隙 元素
.row {
  gap: var(--col-gap);
}
.column {
  outline: var(--col-gap) solid gray;
}

使用 ::after 将内容添加到元素

另外,红点被应用为具有 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 的“仪表板”,它保留在页面顶部并允许您控制:

  • 列宽(px):您可以在此处设置宽度,根据可用的容器空间更改每行的列数
  • 每行列数:在这里您可以设置每行的列数,根据可用的容器空间更改其宽度 宽度
  • 单元格之间的间隙(px):网格上单元格之间的间隙
  • 切换红点可见性:将显示/隐藏红点,再次证明 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  {
    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;
}
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage