【问题标题】:Decrease padding size as parent element getting smaller随着父元素变小,减少填充大小
【发布时间】:2023-01-11 12:56:53
【问题描述】:

我有一个在单元格中绘制正方形的网格。它有行数和列数,然后绘制网格单元格并检查每个单元格中是否应该有一个正方形(根据数组)并在需要时绘制一个正方形。 HTML 最终结果看起来像这样:(假设我有 1 行和 3 列,只有 2 个单元格应该有正方形)

.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>

行占据屏幕的整个宽度,列的大小在所有列之间应该相同,并根据屏幕上的列数变化(例如,如果我有 5 列,它们的宽度都应该为 100px ,但如果我有 1000 列,它们的宽度都应为 10px)。

我的问题是,在列大小的某个断点之后,填充和边框半径看起来很奇怪,我想在遇到该断点时更改它们的值。 我不能使用 @container 查询,因为仍然没有完全支持。

如果它有帮助,我正在使用 vue 2。但我认为在这种情况下 CSS 解决方案会更好。

【问题讨论】:

    标签: html css flexbox


    【解决方案1】:

    试图解决所描述的问题:

    我的问题是,在列大小的某个断点之后 padding 和 border radius 看起来很奇怪,我想改变它们 当我达到那个断点时的值。我不能将@container 查询用作 仍然没有完全支持。

    我制作了一个小演示,帮助我更好地探索导致这种情况的条件。

    获取边框:在 flexbox 项目上折叠等效项

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

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

    因此,为了确保布局不受样式异常的影响,为了展示 flex 项目的边界,该演示仅依赖于 2 个关键方面来呈现这些边界:

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

    使用 ::after 向元素添加内容

    加上红点作为::after伪元素和position:absolute应用,再次确保没有任何影响网格布局:

    .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 的“仪表板”,它保留在页面顶部并允许您控制:

    • 列宽(像素):在这里你设置宽度根据可用的容器空间改变每行的cols
    • 每行列:在这里你设置每行的cols根据可用的容器空间改变它们的宽度 宽度
    • 单元格之间的间隙 (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 <= 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;
    }
    <div id="container" class="row">
      <div class="column square">
      </div>
      <div class="column"></div>
    </div>
    
    <div class="dashboard">
      <div>
        <label for="width">column width (px):</label>
        <input
          id="width" type="number" max="100" min="10">
      </div>
      <div>
        <label for="cols">columns per row:</label>
        <input
          id="cols" type="number" max="50" min="1">
      </div>
      <div>
        <label for="gap">gap between cells (px):</label>
        <input
          id="gap" type="number" max="10" min="0">
      </div>
      <div style="margin-top: 1rem;">
        <label for="toggle-dots">toggle red dots visibility:</label>
        <input id="toggle-dots" type="checkbox" checked>
      </div>
      <div>
        <label for="toggle-counters">toggle counter visibility:</label>
        <input id="toggle-counters" type="checkbox" checked>
      </div>
    </div>

    【讨论】:

      【解决方案2】:

      如果你想增加或减少填充的大小,你可以根据父元素以百分比 (%) 的形式给出填充大小。

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 2015-08-23
        • 2014-10-29
        • 1970-01-01
        相关资源
        最近更新 更多