Razor 构建包含N列、2行、容器最大高度的CSS网格

Razor 构建包含N列、2行、容器最大高度的CSS网格,razor,css-grid,Razor,Css Grid,CSS中的网格是新的,当然,从更复杂的需求开始 想象一下机场到港/离港显示。没有键盘,没有鼠标,没有人机交互。这个调用应用程序过去只是一个大的长滚动列表。我正在把它变成一个更有条理的布局。根据它最终显示在哪个屏幕上,它可能有空间容纳2列,3列,甚至5列-其中每列的宽度相同,并且有一个最小宽度 第一行:页眉/全宽/3行文本 第二排:应等于剩余高度、全宽,是一个容器 在容器中: 2行(标题行、内容行) N列(其中列具有最小宽度)-->也是用于字幕中文本的视图面板(垂直 通过js滚动) 由于返回的

CSS中的网格是新的,当然,从更复杂的需求开始

想象一下机场到港/离港显示。没有键盘,没有鼠标,没有人机交互。这个调用应用程序过去只是一个大的长滚动列表。我正在把它变成一个更有条理的布局。根据它最终显示在哪个屏幕上,它可能有空间容纳2列,3列,甚至5列-其中每列的宽度相同,并且有一个最小宽度

第一行:页眉/全宽/3行文本
第二排:应等于剩余高度、全宽,是一个容器
在容器中:

  • 2行(标题行、内容行)
  • N列(其中列具有最小宽度)-->也是用于字幕中文本的视图面板(垂直 通过js滚动)

由于返回的模型集合可能具有未知数量的时间/列表集,因此我尝试让自动化完成一些工作。其想法是,如果我有超过所能容纳的列数,那么它们要么是
(A)
不显示,要么是
(B)
包裹在屏幕底部,实际上是隐藏的。

因此,在CSS中跳入flex vs grid之后,我稍微改变了我的方法。
容器
以这种方式重写:

<section class="wrapper">
    <ul class="colList">
        @foreach (var kvp in Model.ResultList.OrderBy(a => a.Key))
        {
            <li class="columnItem">
                <div class="columnTitle--wrapper">
                    <h2>&gt;&gt;&gt; @kvp.Key</h2>
                </div>
                <div class="cardViewer">
                    <div class="cardList">
                        <ul class="cardList--ul">
                            @foreach (var subject in kvp.Value.OrderBy(a => a.EventTitle).ThenBy(a => a.LastName).ThenBy(a => a.SubjectId))
                            {
                                <li class="cardItem">
                                    <h3>@subject.EventTitle.ToUpper()</h3>
                                    <h3>@subject.LastName.ToUpper()</h3>
                                    <h3>#@subject.SubjectId.ToUpper()</h3>
                                </li>
                            }
                        </ul>
                    </div>
                </div>
            </li>
        }
    </ul>
</section>
我还添加了JS,以便在需要时处理多个选框(列表对于视口来说太长):

class marqueeInfo{
构造函数(查看器、卡片列表){
this.viewer=查看器;
this.cardList=cardList;
如果(这个是可循环的){
this.cardList.style.top=parseInt(this.viewerHeight())+“px”
}
否则{
this.cardList.style.top=“0px”
}
}
查看器(){返回this.viewer;}
cardList(){返回this.cardList;}
viewerHeight(){返回this.viewer.offsetHeight;}
cardListHeight(){返回this.cardList.offsetHeight;}
isScrollable(){返回this.cardList.offsetHeight>this.viewer.offsetHeight;}
}
var-marqueeArray=[];
var marqueeSpeed=4//指定选框滚动速度(越大,速度越快1-10)
var delayb4scroll=100//指定字幕开始在页面上滚动之前的初始延迟(2000=2秒)
var lastRefresh;
var isRefreshing=错误;
var refreshMinutes=1;
//这可能太过分了。。。
if(window.addEventListener)
addEventListener(“加载”,initializeMarqueeHandler,false)
else if(窗口附件)
attachEvent(“onload”,initializeMarqueHandler)
else if(document.getElementById)
window.onload=initializeMarqueeHandler
函数initializeMarqueeHandler()的缩写{
lastRefresh=新日期();
isRefreshing=假;
var viewers=document.getElementsByClassName(“cardViewer”);
var卡;
var i;
对于(i=0;itargetTop)//我们是否已通过列表?
marquee.cardList.style.top=cardTop-marqueeSpeed+“px”//滚动
其他的
marquee.cardList.style.top=viewerHeight+25+“px”;
}
否则{
marquee.cardList.style.top=“0px”;
}
})
变量毫秒=(新日期()).getTime()-lastRefresh.getTime();
如果(毫秒>(刷新分钟数*60*1000)和(!isRefreshing){
lastRefresh=新日期();
isRefreshing=真;
window.location.reload(true);
}
}
一切都在按预期进行——最后

.header {
    padding: 5px;
    border: groove;
    border-bottom-color: black;
    border-width: 2px;

    /* Grid styles */
    display: grid;
    align-items: center;
    /*grid-template-columns: 1fr;*/
    grid-template-rows: repeat(3, 1fr);
}
.container {
    max-height: 100vh;

    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 30px auto-fill;
    grid-gap: 5px;
}
.timeDisplay{
    max-height: 30px;
}
.viewPort {
    height: 100%;
    overflow: hidden;
}
.textList {
    height: 100%;
    font-size: 125%;
    display: grid;
    grid-template-columns: 3fr 2fr 5fr;
}
<section class="wrapper">
    <ul class="colList">
        @foreach (var kvp in Model.ResultList.OrderBy(a => a.Key))
        {
            <li class="columnItem">
                <div class="columnTitle--wrapper">
                    <h2>&gt;&gt;&gt; @kvp.Key</h2>
                </div>
                <div class="cardViewer">
                    <div class="cardList">
                        <ul class="cardList--ul">
                            @foreach (var subject in kvp.Value.OrderBy(a => a.EventTitle).ThenBy(a => a.LastName).ThenBy(a => a.SubjectId))
                            {
                                <li class="cardItem">
                                    <h3>@subject.EventTitle.ToUpper()</h3>
                                    <h3>@subject.LastName.ToUpper()</h3>
                                    <h3>#@subject.SubjectId.ToUpper()</h3>
                                </li>
                            }
                        </ul>
                    </div>
                </div>
            </li>
        }
    </ul>
</section>
/* column styles */
.wrapper {
}

.colList {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
    grid-gap: .5rem;
    align-items: start;
    top: 500vh;
}

.columnItem {
    border-radius: .2rem;
    padding: .5rem;
}

.columnTitle--wrapper {
}

    .columnTitle--wrapper h2 {
        font-weight: 700;
    }

/* card styles */
.cardViewer {
    overflow: hidden;
    height: 80vh;
    max-height: 80vh;
}

.cardList {
    position: relative;
}

.cardList--ul {
    display: grid;
    grid-template-rows: auto;
    grid-gap: .5rem;
    margin: .5rem 0;
}

.cardItem {
    background-color: white;
    border: 1px solid #BBB;
    border-radius: .25rem;
    box-shadow: 0 1px 0 rgba(9,45,66,.25);
    padding: .5rem;

    display: grid;
    grid-template-columns: 5fr 7fr 2fr;
}
class marqueeInfo {
    constructor(viewer, cardList) {
        this.viewer = viewer;
        this.cardList = cardList;

        if (this.isScrollable) {
            this.cardList.style.top = parseInt(this.viewerHeight()) + "px"
        }
        else {
            this.cardList.style.top = "0px"
        }
    }

    viewer() { return this.viewer; }
    cardList() { return this.cardList; }
    viewerHeight() { return this.viewer.offsetHeight; }
    cardListHeight() { return this.cardList.offsetHeight; }
    isScrollable() { return this.cardList.offsetHeight > this.viewer.offsetHeight; }
}

var marqueeArray = [];
var marqueeSpeed = 4    //Specify marquee scroll speed (larger is faster 1-10)
var delayb4scroll = 100 //Specify initial delay before marquee starts to scroll on page (2000=2 seconds)
var lastRefresh;
var isRefreshing = false;
var refreshMinutes = 1;

// may be overkill here...
if (window.addEventListener)
    window.addEventListener("load", initializeMarqueeHandler, false)
else if (window.attachEvent)
    window.attachEvent("onload", initializeMarqueeHandler)
else if (document.getElementById)
    window.onload = initializeMarqueeHandler


function initializeMarqueeHandler() {
    lastRefresh = new Date();
    isRefreshing = false;
    var viewers = document.getElementsByClassName("cardViewer");
    var cards;
    var i;
    for (i = 0; i < viewers.length; i++) {
        cards = viewers[i].getElementsByClassName("cardList");
        if (cards.length != 1)
            return;
        marqueeArray.push(new marqueeInfo(viewers[i], cards[0]));
    }
    setTimeout('lefttime=setInterval("scrollMarquees()",30)', delayb4scroll)
}

function scrollMarquees() {
    marqueeArray.forEach(function (marquee, index, array) {
        if (marquee.isScrollable()) {
            var cardHeight = marquee.cardListHeight();
            var viewerHeight = marquee.viewerHeight();
            var cardTop = parseInt(marquee.cardList.style.top);
            var targetTop = 0 - cardHeight;
            if (cardTop > targetTop)  // are we thru the list?
                marquee.cardList.style.top = cardTop - marqueeSpeed + "px" //scroll
            else
                marquee.cardList.style.top = viewerHeight + 25 + "px";
        }
        else {
            marquee.cardList.style.top = "0px";
        }
    })

    var milliseconds = (new Date()).getTime() - lastRefresh.getTime();
    if (milliseconds > (refreshMinutes * 60 * 1000) && !isRefreshing) {
        lastRefresh = new Date();
        isRefreshing = true;
        window.location.reload(true);
    }
}