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