CSS网格体育场形状

5

我一直在尝试使用CSS Grid处理以下图片,但这非常具有挑战性。

enter image description here

这张图片代表了一个体育场,但要让它看起来像附加的图片非常困难。需要注意以下几点:

  • 四个角是三角形,所以最难的部分是使它们保持这种形状并且具有响应性。

  • 可以使用CSS Mask来处理形状和间距,但这将切掉一些圆圈。

我尝试了很多次,只完成了一半。有什么想法可以帮助我让它正常工作吗?或者如果有人有不同的方法也可以帮助我。

https://jsfiddle.net/rodboc/9psa4bg3/1/

有任何想法吗?

.grid {
  max-width: 80vw;
  min-height: 90vh;
  display: grid;
  grid-gap: 5px;
  grid-template-columns: 30% [main-start] 40% [main-end] 30%;
  grid-template-rows: 20% [main-start] 30% [main-end] 20%;
  margin: 0 auto;
}

[class^="item"] {
  background-color: blue;
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  align-items: flex-start;
  align-content: flex-start;
  justify-content: center;
}

.item1 {
  background-color: red;
  grid-area: main;
}
.circle {
  width: 5px;
  height: 5px;
  overflow: hidden;
  background: #ccc;
  border-radius: 50%;
  margin: 1px;
  padding: 0;
}

.circle:hover {
  background: blue;
}

<div class="grid">
  <div class="item1">
  </div>
  <div class="item2">
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
    <div class="circle"></div>
  </div>
  <div class="item3"></div>
  <div class="item4"></div>
  <div class="item5"></div>
  <div class="item6"></div>
  <div class="item7"></div>
  <div class="item8"></div>
  <div class="item9"></div>
</div>

1
就此而言,您嵌入的示例图片在 SO 的暗模式下完全不可见。 - Alexander Nied
谢谢,我会添加一个背景颜色。 - rodboc
1个回答

6

shape-outside 是你需要的。

这里有一个基本的想法,你可以轻松地复制到底部:

body {
  width:780px;
}

.top {
  height:150px;
  text-align:justify;
}
i {
  display:inline-block;
  width:30px;
  height:30px;
  margin:2px;
  background:red;
  border-radius:50%;
}
.top::before {
  content:"";
  height:100%;
  width:150px;
  float:left;
  shape-outside:linear-gradient(to bottom left,transparent 49%,#fff 50%);
}
.top span::before {
  content:"";
  height:100%;
  width:150px;
  float:right;
  shape-outside:linear-gradient(to bottom right,transparent 49%,#fff 50%);
}

.left,
.right{
   width:150px;
   height:150px;
   float:left;
   transform:translateY(-90%);
   clip-path:polygon(0 0,100vh 100vh,0 100vh );
} 
.left::before,
.right::before{
  content:"";
  height:100%;
  width:100%;
  float:right;
  shape-outside:linear-gradient(to bottom left,#fff 49%,transparent 50%);
}
.right {
  float:right;
  text-align:right;
   clip-path:polygon(-100vh 100vh,100vh 100vh,100% 0);
}
.right::before{
  float:left;
  shape-outside:linear-gradient(to bottom right,#fff 49%,transparent 50%);
}

i:hover{
  background:blue;
}
<div class="top"><span></span>
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
</div>

<div class="left">
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
</div>

<div class="right">
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
</div>

更新

体育场形状的完整示例:

var t = document.querySelector('.top');
var tl = document.querySelector('.top-left');
var tr = document.querySelector('.top-right');
var b = document.querySelector('.bottom');
var bl = document.querySelector('.bottom-left');
var br = document.querySelector('.bottom-right');
var sl = document.querySelector('.side-left');
var sr = document.querySelector('.side-right');
for (var i = 0; i < 5000; i++) {
  var l = document.createElement("i");
  t.appendChild(l);
  l = document.createElement("i");
  tl.appendChild(l);
  l = document.createElement("i");
  tr.appendChild(l);
  l = document.createElement("i");
  b.appendChild(l);
  l = document.createElement("i");
  bl.appendChild(l);
  l = document.createElement("i");
  br.appendChild(l);
  l = document.createElement("i");
  sl.appendChild(l);
  l = document.createElement("i");
  sr.appendChild(l);
}
body {
  margin: 0;
}

.stadium {
  display: grid;
  min-width:600px;
  min-height:500px;
  grid-template-columns: 20% 1fr 20%;
  grid-template-rows: 150px 1fr 150px;
  row-gap:10px;
  height: 100vh;
  line-height: 0;
}

.top,
.bottom{
  height: 100%;
  grid-column: 1/-1;
  grid-row: 1;
  text-align: justify;
  overflow: hidden;
}
.bottom {
  grid-row: 3;
}

.top::before,
.bottom::before{
  content: "";
  height: 100%;
  width: 20%;
  float: left;
  shape-outside: linear-gradient(to bottom left, transparent 49%, #fff 50%);
}
.bottom::before{
  shape-outside: linear-gradient(to top left, transparent 49%, #fff 50%);
}

.top span::before,
.bottom span::before {
  content: "";
  height: 100%;
  width: 20%;
  float: right;
  shape-outside: linear-gradient(to bottom right, transparent 49%, #fff 50%);
}
.bottom span::before {
  shape-outside: linear-gradient(to top right, transparent 49%, #fff 50%);
}

.top-left,
.top-right,
.bottom-left,
.bottom-right{
  width: 100%;
  height: 100%;
  float: left;
  grid-row: 1;
  grid-column: 1;
  overflow: hidden;
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

.bottom-left {
  grid-row: 3;
  grid-column: 1;
  clip-path: polygon(0 0, 100% 0,0 100%);
}


.top-left::before,
.top-right::before,
.bottom-left::before,
.bottom-right::before{
  content: "";
  height: 100%;
  width: 100%;
  float: right;
  shape-outside: linear-gradient(to bottom left, #fff 49%, transparent 50%);
}
.bottom-left::before {
  shape-outside: linear-gradient(to top left, #fff 49%, transparent 50%);
}
.top-right,
.bottom-right{
  float: right;
  text-align: right;
  grid-column: 3;
  clip-path: polygon(0 100%, 100% 100%, 100% 0);
}
.bottom-right {
  grid-row: 3;
  clip-path: polygon(0 0, 100% 0,100% 100%);
}

.top-right::before {
  float: left;
  shape-outside: linear-gradient(to bottom right, #fff 49%, transparent 50%);
}
.bottom-right::before {
  float: left;
  shape-outside: linear-gradient(to top right, #fff 49%, transparent 50%);
}

.side-right,
.side-left {
 height:100%;
 overflow:hidden;
}
.side-right {
  grid-column:3;
  text-align:right;
}

i {
  display: inline-block;
  vertical-align: top;
  width: 8px;
  height: 8px;
  margin: 1px;
  background: red;
  border-radius: 50%;
}

i:hover {
  background: blue;
}
<div class="stadium">
  <div class="top-left"></div>
  <div class="top"><span></span></div>
  <div class="top-right"></div>
  
  <div class="bottom-left"></div>
  <div class="bottom"><span></span></div>
  <div class="bottom-right"></div>
  
  <div class="side-left"></div>
  <div class="side-right"></div>
</div>


很遗憾,这不是我想要的,因为边框对于鼠标操作(如悬停或点击)变得无法访问。 - rodboc
那些靠近边缘的圆圈不能被悬停,因为它们使用了shape-outside属性。 https://jsfiddle.net/Gemobu/g4057zsa/1/ @temaniafif - rodboc
@rodboc 它们可以被悬停,检查更新。剪辑路径可以解决这个问题。 - Temani Afif
@rodboc 不会,剪辑路径将遵循使用 shape-outside 创建的形状来切割创建悬停问题的额外部分。 - Temani Afif
使用clip-path和shape-outside时存在不可达区域https://jsfiddle.net/Gemobu/f40mp18b/,仔细查看后,每个块都应该重叠在下一个块上@temaniafif - rodboc
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接