仅当标题到达特定列时才如何修复列(使用CSS网格)? [英] How to fix a column (with css grid) only when the header hits a specific column?

查看:57
本文介绍了仅当标题到达特定列时才如何修复列(使用CSS网格)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  headerheaderheader 
mainmainmainmain
col1col1col col2

我想在这里实现两件事:


  1. 必须 col2 在向下滚动时固定在屏幕上。

  2. 仅在标题时保持 col2 固定击中列。这是固定的标头。

我尝试了添加固定/粘性的位置,但在这种情况下似乎不起作用。该列将消失。我的React组件的结构是这样的:

 < Header /> 
<中间件/>

//下面是中间件
< main>
< form className =" booking-form"< / form>
<选择/>
< / main>

//位于选择项内部
< div className = selection>< / div>
< BookingDetail />

//最后,在BookingDetail

这是我的html呈现时的样子:

 < header>这是固定的标头< / header>。 
< main class = form-container>
< form class = booking-form>水平地占据100%< / form>
< div class = selection>在水平< / div>下,水平占据大约80%。
< div class = booking-detail>在水平方向上约占20%< / div>
< / main>

最后,css

 。表格容器{
display:grid;
grid-template-columns:repeat(24,1fr);
}
.booking-form {
grid-column:3 / span 20; //占据整行,请参见
上方的 main}
.selection {//左列(col1)
grid-column:3 / span 15;
}
.booking-detail {//右列(col2),当标题被击中时,我需要对其进行修复。
显示:块; //显示处于阻塞状态,因为在较小的断点处显示为:none;’
grid-column:19 / -2;
}

编辑:
Kenan的答案非常有用,除了我一直在尝试的一个小错误修理。由于滚动代码,选择列中的内容(某些具有内部内容的div)的大小意外地调整了大小,我无法解决该问题。这些是其内部内容(其中有很多)

 < div className = business-and-timegrid-wrapper; key = {index}> 
< Estabelecimento
logoURL = {item.logoURL}
名称= {item.name}
等级= {item.rating}
地址= {item.address }
/>
{item&& < TimeGridSelection item = {item} date = {dateForRenderingTimeGrid} />}
< / div>
------------------------------------
.business-and-timegrid -wrapper {
padding:1em;
底边保证金:-3vh;
background-color:#fff;
显示:网格;
grid-template-columns:repeat(2,50%);
边框:1px #ECECEC实体;
框阴影:0px 3px 6px#00000029;
不透明度:1;
}


解决方案

更新



我不知道您对React有多少了解,但是会以您确实影响React应用程序的方式编写JS吗?


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


我创建了一个简单的React应用程序,并将所有内容(我最初发布的内容)放在了其中,并进行了相应的调整。不幸的是,我对React并不了解很多,但是基本上它应该使您了解如何使用React来实现。





原始答案


如果我对您的理解是正确的,那么仅凭CSS就无法实现这一目标(希望其他人可以证明我错了);因此,您需要在这里从JavaScript中获得一些帮助。


顺便说一句,通常不会用 header将 main包装起来。 (请参见 HTML< main>标记)。


尝试一下(请注意,在此示例中,我使用了简单的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);

函数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(固定);
}
} else {
bookingDetailContentElem.classList.remove( fixed);
}
}
window.addEventListener( scroll,checkBookingDetailContent);
window.addEventListener( resize,checkBookingDetailContent);
checkBookingDetailContent();
}

  * {
框-sizing:边框框;
颜色:#fff;
填充:0;
保证金:0;
}

html,正文{
display:block;
宽度:100%;
背景:黑色;
身高:200%;
}

#page-header {
背景:蓝色;
高度:100像素;
头寸:粘性;
top:0;
z-index:2;
}

.form-container {
display:flex;
flex-direction:列;
头寸:粘性;
}

.form-container .booking-form {
背景:红色;
高度:250像素;
}

.form-container .col-wp {
height:500px;
溢出:隐藏;
}

.form-container .col-wp .selection {
背景:绿色;
浮动:左;
宽度:80%;
身高:100%;
}

.form-container .col-wp .booking-detail {
width:20%;
身高:100%;
float:正确;
}

#booking-detail-content {
背景:橙色;
z-index:1;
}

#booking-detail-content.fixed {
位置:固定;
top:100像素;
}

 < html> 
< body>
< header id = page-header>
这是我的标头
< / header>
< main class = form-container>
< form class = booking-form>水平地占据100%< / form>
< div class = col-wp>
< div class = selection>沿水平方向占据约80%< / div>
< div class = booking-detail>
< div id = booking-detail-content>
水平占据约20%的空间
< / div>
< / div>
< / div>
< / main>
< / body>
< / html>


Visually, it looks somewhat like this:

headerheaderheader
 mainmainmainmain
 col1col1col col2

I am trying to achieve two things here:

  1. have col2 be fixed on the screen when scrolling down.
  2. only keep col2 fixed when the header hits the columns. It's a fixed header.

I've tried adding position fixed/sticky but that doesn't seem to work in this case. That column simply disappears. My React components are structured this way:

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

This is what my html looks like when rendered:

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

Finally, the 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;
}

EDIT: Kenan's answer works great except for a little bug I've been trying to fix. The contents inside of the 'selection' col (some divs with internal content) are unexpectedly resizing because of the scroll code and I cannot figure out how to fix it. These are its internal content (there are many of these)

<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;
}

解决方案

Update

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

Well, writing JS the way I did would still work in React without any problems. But since you are using React, it puts everything inside a div element (the so-called root), so in some cases it might not work for the header element...

I created a simple React application and have put everything - I originally posted - there and adapted it accordingly. Unfortunately I don't have much knowledge about React, but basically it should give you an idea of how you can achieve this with React.


Original answer

If I understood you correctly, you can't achieve this with CSS alone (hopefully someone else can prove me wrong); so you need a little help from JavaScript here.

By the way, it is not usual to wrap the 'main' by a 'header'. (see HTML <main> Tag).

Try this one (Note that I used simple JavaScript in this example, but you can adjust it according to the framework of your choice):

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>

这篇关于仅当标题到达特定列时才如何修复列(使用CSS网格)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆