【问题标题】:horizontal scroll with 100% width on grid cell网格单元格上 100% 宽度的水平滚动
【发布时间】:2022-01-17 20:11:35
【问题描述】:

我想要一个 CSS 网格,在网格的每个单元格内,我想要一个最大尺寸为单元格宽度 100% 的标题。如果标题太长,我想滚动。

这是当前具有正确滚动行为但在长标题上具有固定宽度的外观。我想要的不是固定宽度,而是单元格宽度的 100%(所以灰色块应该和红色框一样长)

codePen:https://codepen.io/vincent2303/pen/ExwZEpW

* {
  margin: 0;
  padding: 0;
}

body {
  padding: 50px;
}

h2 {
  font-size: 2em;
  white-space: nowrap;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  width: 800px;
  gap: 20px;
}

.box {
  background-color: #e74c3c;
  height: 30vh;
}

.title-wrapper {
  background-color: #bdc3c7;
  width: 300px;
  overflow-x: scroll;
}
<div class=grid>

  <div>
    <div class="title-wrapper">
      <h2>long title, i can scroll---------</h2>
    </div>

    <div class="box"></div>
  </div>

  <div>
    <h2>Short title</h2>
    <div class="box"></div>
  </div>

</div>

有人有这个想法吗?

注意:为了简化代码示例,.grid 类的宽度为 800px,但实际上,它的宽度由其父级定义,我无法预测宽度(我正在研究react app,这段代码将实现一个在多个地方使用的组件,大小不同)。

【问题讨论】:

  • 你认为让红框比灰框的高度更大,而不是使用红框的 100% 宽度作为灰框的最大宽度并将红框与灰色框重叠一个带有“z-index”的可以接受吗?
  • 感谢您的回答。我不能使用最大宽度,因为我不知道网格的宽度。

标签: html css frontend


【解决方案1】:

1fr 解析为minmax(auto, 1fr),这意味着网格列的最小宽度为min-content,大于1fr。这个问题有一个快速的解决方案,只需将1fr 替换为minmax(0px, 1fr),这样,父级的宽度被划分为两列,这样你就有了你想要的滚动条。

* {
  margin: 0;
  padding: 0;
}

body {
  padding: 50px;
}

h2 {
  font-size: 2em;
  white-space: nowrap;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

.box {
  background-color: #e74c3c;
  height: 30vh;
}

h2 {
  background-color: #bdc3c7;
  overflow-x: auto;
}
<div class=grid>

  <div>
    <h2>long title, i can scroll----------------------------</h2>
    <div class="box"></div>
  </div>

  <div>
    <h2>Short title</h2>
    <div class="box"></div>
  </div>

</div>

【讨论】:

    【解决方案2】:

    如果您的网格可能包含溢出的内容,则无法使用 1fr,原因如下:

    • 1frminmax(auto, 1fr) 的缩写。
    • a &gt;= btrue 时,minmax(a, b) 变为 a(没有任何最小值)。
    • 因此,在您的情况下,您的网格的行为就像您将其定义为 grid-template-columns: auto 1fr;,因为对于您的第一列,auto 大于 1fr

    要解决这个问题,您需要告诉网格,当内容变得太宽时,不允许扩展单元格。

    使用minmax(0, 1fr) 代替1fr

    * {
      margin: 0;
      padding: 0;
    }
    
    body {
      padding: 50px;
    }
    
    h2 {
      font-size: 2em;
      white-space: nowrap;
    }
    
    .grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      width: 800px;
      gap: 20px;
    }
    
    .box {
      background-color: #e74c3c;
      height: 30vh;
    }
    
    h2 {
      background-color: #bdc3c7;
      overflow-x: scroll;
    }
    <div class=grid>
    
      <div>
        <h2>long title, i can scroll------------------ - - - - ----</h2>
        <div class="box"></div>
      </div>
    
      <div>
        <h2>Short title</h2>
        <div class="box"></div>
      </div>
    
    </div>

    【讨论】:

    • 完美,非常感谢!我不知道 fr 单位是这样工作的(我以为 if 只是一个百分比)。
    • 我刚刚接受了您的解决方案。我试图支持您的解决方案,但我没有足够的声誉这样做。再次感谢你:)
    【解决方案3】:

    如果没有 JavaScript 似乎很难,Dev 他的答案有效,但它涉及固定的最大宽度。

    我有一个似乎可行的 JavaScript 解决方案。

        /* Execute when the DOM is loaded, because otherwise the HTML elements might nog be in the DOM. */
        window.addEventListener( 'DOMContentLoaded', () => {
    
            generateGridItemsWidthVariable()
    
        } )
    
        /* Execute when the window is resized, because the width of the boxes might change. */
        window.addEventListener( 'resize', () => {
    
            generateGridItemsWidthVariable()
    
        } )
    
        /* Generate the variable for the grid items. */
        function generateGridItemsWidthVariable() {
    
            /* Select all the grid items and create an array to loop trough. */
            let gridItems = Array.from( document.getElementsByClassName( 'grid__item' ) )
    
            /* Loop trough the grid items. */
            gridItems.forEach( gridItem => {
    
                /* Reset the grid item width, because otherwise the item won't resize. */
                gridItem.style.setProperty( '--grid-item--width', '' )
    
                /* Get the width of the grid item. */
                let gridItemWidth = gridItem.clientWidth.toString()
                /* Set the width of the grid item as a CSS variable. */
                gridItem.style.setProperty( '--grid-item--width', gridItemWidth + 'px' )
    
            } )
    
        }
        * {
            margin: 0;
            padding: 0;
        }
    
        body {
            padding: 50px;
        }
    
        h2 {
            font-size: 2em;
            white-space: nowrap;
        }
    
        .grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            width: 100%;
            max-width: 800px;
            gap: 20px;
        }
    
        .grid__item {
            --grid-item--width: 10px;
        }
    
        .box {
            background-color: #e74c3c;
            height: 30vh;
        }
    
        .title-wrapper {
            background-color: #bdc3c7;
            width: 100%;
        }
        .title-wrapper h2 {
            max-width: var(--grid-item--width);
            overflow-x: scroll;
        }
    <div class=grid >
    
        <div class="grid__item">
            <div class="title-wrapper" >
                <h2>long title, i can scroll-----------------------</h2>
            </div>
    
            <div class="box" ></div>
        </div>
    
        <div class="grid__item">
            <h2>Short title</h2>
            <div class="box" ></div>
        </div>
    
    </div>

    【讨论】:

    • 感谢您提供此解决方案。不幸的是,我正在开发 react 应用程序,我认为使用 javascript 来操作 DOM 元素是我应该避免的。
    • 啊,知道了@VinceM。你必须使用grid还是所有CSS都可用?
    • 所有 css 都可以使用。但是我想要构建的是一个复杂的网格,我认为例如使用 flexbox 会非常困难。这是我正在尝试构建的网格的图像示例:sparkbox.com/uploads/article_uploads/…
    • 网格是这里的完美解决方案。不需要 JS。请参阅下面的答案。
    【解决方案4】:

    这里有一种可能性:

    * {
      margin: 0;
      padding: 0;
    }
    
    body {
      padding: 50px;
    }
    
    h2 {
      font-size: 2em;
      
      white-space: nowrap;
    }
    
    .grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      width: 800px;
      gap: 20px;
    }
    
    .box {
      background-color: #e74c3c;
      height: 50vh;
      max-width: 400px;
    }
    
    .title-wrapper {
      background-color: #bdc3c7;
      width: 100%;
      overflow-x: scroll;
    }
    <div class=grid >
    
        <div>
        
    
          <div class="box" >
              <div class="title-wrapper" >
            <h2>long title, i can scroll---------------------------------</h2>
          </div>
          </div>
        </div>
    
        <div>
        
          <div class="box" >
              <h2>Short title</h2>
          </div>
        </div>
    
     </div>

    【讨论】:

    • 感谢您的回答。不幸的是,我不能使用最大宽度框,因为我不知道框的宽度。在给定的示例中,网格的宽度是 800px,但实际上它是由父宽度决定的。
    • 它应该仍然可以工作。灰色框的宽度仅为红色框宽度的 100%,因此更改红色框的宽度会影响灰色框的宽度。我使用最大宽度只是为了测试当红色框具有给定宽度时滚动的可能性
    • 如果我删除 box 类的 max-width 属性,它会改变网格的形状(左列变得比第二列大得多)。代码笔:codepen.io/vincent2303/pen/NWadYXm
    猜你喜欢
    • 2019-07-11
    • 2014-01-25
    • 1970-01-01
    • 2012-06-13
    • 2012-04-05
    • 2011-05-16
    • 2017-03-02
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多