如何仅在 header 命中特定列时修复列(使用 css 网格)?

How to fix a column (with css grid) only when the header hits a specific column?

从视觉上看,它看起来有点像这样:

headerheaderheader
 mainmainmainmain
 col1col1col col2

我想在这里实现两件事:

  1. 向下滚动时 col2 固定在屏幕上。
  2. 仅在 header 命中列时保持 col2 固定。这是固定的 header.

我试过 但在这种情况下似乎不起作用。那一列就消失了。我的 React 组件是这样构造的:

<Header />
<Middleware />

//below is inside of Middleware
<main>
  <form className="booking-form"></form>
  <Selection/>
</main>

//below is inside of Selection
<div className="selection"></div>
<BookingDetail/>

//finally, inside of BookingDetail
<div className="booking-detail"></div>

这是我的 html 渲染后的样子:

<header> This is the fixed header </header>
<main class="form-container">
  <form class="booking-form"> takes up 100% horizontally </form> 
  <div class="selection"> takes up about 80% horizontally, below form </div>
  <div class="booking-detail"> takes up about 20% horizontally </div>
</main>

最后,css

.form-container {
   display: grid;
   grid-template-columns: repeat(24, 1fr);
}
.booking-form {
   grid-column: 3 / span 20;   // takes up entirety of row, see 'main' above
}
.selection {                  //left column (col1)
   grid-column: 3 / span 15;
}
.booking-detail {             //right column (col2), which I need fixed when the header hits.
   display: block;             //display is block as at a smaller break point it's 'display: none;'
   grid-column: 19 / -2;
}

编辑: 除了我一直试图修复的一个小错误外,Kenan 的回答非常有效。由于滚动代码,'selection' col 中的内容(一些具有内部内容的 div)意外地调整了大小,我不知道如何修复它。这些是它的内部内容(有很多这样的)

<div className="business-and-timegrid-wrapper" key={index}>
   <Estabelecimento
      logoURL={item.logoURL}
      name={item.name}
      rating={item.rating}
      address={item.address}
    />
    {item && <TimeGridSelection item={item} date={dateForRenderingTimeGrid} />}
      </div>
------------------------------------
.business-and-timegrid-wrapper {
   padding: 1em;
   margin-bottom: -3vh;
   background-color: #fff;
   display: grid;
   grid-template-columns: repeat(2, 50%);
   border: 1px #ECECEC solid;
   box-shadow: 0px 3px 6px #00000029;
   opacity: 1;
}

更新

I don't know how much you know about React, but would writing JS the way you did affect my React app?

好吧,按照我的方式编写 JS 仍然可以在 React 中正常工作,没有任何问题。但是由于您使用的是 React,它将所有内容都放在 div 元素(so-called root)中,因此在某些情况下它可能不适用于 header 元素。 .

我创建了一个简单的 React 应用程序,并将我最​​初发布的所有内容都放在那里并相应地对其进行了调整。不幸的是,我对 React 了解不多,但基本上它应该让您了解如何使用 React 实现这一目标。


原回答

如果我没理解错的话,单靠 CSS 是无法做到这一点的(希望别人能证明我是错的);所以你需要 JavaScript 的帮助。

顺便说一下,用 'header' 包裹 'main' 是不常见的。 (参见 HTML <main> Tag)。

试试这个(注意我在这个例子中使用了简单的JavaScript,但是你可以根据你选择的框架进行调整):

JSFiddle:https://jsfiddle.net/od9jf4m7/

window.onload = function() {
    var pageHeaderElem = document.getElementById("page-header");
    var bookingDetailElem = document.getElementsByClassName("booking-detail")[0];
    var bookingDetailContentElem = document.getElementById("booking-detail-content");

    function checkBookingDetailContent() {
        bookingDetailContentElem.style.width = bookingDetailContentElem.parentElement.offsetWidth + 'px';
        bookingDetailContentElem.style.height = bookingDetailContentElem.parentElement.offsetHeight + 'px';
        if(bookingDetailElem.getBoundingClientRect().top < pageHeaderElem.offsetHeight) {
            if(!bookingDetailContentElem.classList.contains("fixed")) {
                bookingDetailContentElem.classList.add("fixed");
            }
        } else {
            bookingDetailContentElem.classList.remove("fixed");
        }
    }
    window.addEventListener("scroll", checkBookingDetailContent);
    window.addEventListener("resize", checkBookingDetailContent);
    checkBookingDetailContent();
}
* {
    box-sizing: border-box;
    color: #fff;
    padding: 0;
    margin: 0;
}

html, body {
    display: block;
    width: 100%;
    background: black;
    height: 200%;
}

#page-header {
    background: blue;
    height: 100px;
    position: sticky;
    top: 0;
    z-index: 2;
}

.form-container {
    display: flex;
    flex-direction: column;
    position: sticky;
}

.form-container .booking-form {
    background: red;
    height: 250px;
}

.form-container .col-wp {
    height: 500px;
    overflow: hidden;
}

.form-container .col-wp .selection {
    background: green;
    float: left;
    width: 80%;
    height: 100%;
}

.form-container .col-wp .booking-detail {
    width: 20%;
    height: 100%;
    float: right;
}

#booking-detail-content {
    background: orange;
    z-index: 1;
}

#booking-detail-content.fixed {
    position: fixed;
    top: 100px;
}
<html>
    <body>
    <header id="page-header">
        This is my header
    </header>
    <main class="form-container">
        <form class="booking-form">takes up 100% horizontally</form>
        <div class="col-wp">
            <div class="selection">takes up about 80% horizontally</div>
            <div class="booking-detail">
                <div id="booking-detail-content">
                    takes up about 20% horizontally
                </div>
            </div>
        </div>
    </main>
    </body>
</html>

The green col (as per your coloration) is undergoing some internal resizing and I can't figure out why. It's the many divs I have inside of it that somehow are being affected by the scroll code. I edited the question to reflect this.

很抱歉没有考虑到虽然您最初使用 CSS 网格布局,但我在解决方案中使用了 flex 布局。所以,这次我专门使用了网格布局。由于我之前的回答被接受了,我不想再碰它了,所以这里是第二个答案。

看看这个:

参考文献: