间隙为0px的CSS网格中的SVG显示背景颜色 [英] SVGs in a CSS Grid with 0px gap displays background color

查看:42
本文介绍了间隙为0px的CSS网格中的SVG显示背景颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SVG占据了CSS-Grid单元格的100%(间距:0px)

JSFiddle,位于:

  • 每个SVG中的额外< rect width ='100%'wheight ='100%'fill ='blue'/> 确实显示出更多多余的间隙.

  • 在网格的右侧还有一条多余的线/间隙.

是否需要SVG或CSS Grid修复程序?

更新1

..在Chrome中很好.

在FireFox中,显示红色背景线.来自答案的102%溢出修复"将应用于鼠标悬停.(但这确实会垂直拉伸SVG)

 < style>身体 {--width:177px;/*模拟响应错误行*/--Xwidth:180像素;/* N x 10像素修复"了不必要的间隙*/-溢出:100%;/*请参阅下方的建议修复" */背景:darkslategrey;}#Tiles {宽度:var(-width);高度:var(-width);显示:网格;grid-template-columns:repeat(10,1fr);grid-template-rows:repeat(10,1fr);间隙:0px;背景:红色;/*应该不可见!*/框大小:border-box;边框:2px纯黄色;溢出:隐藏}#Tiles:hover {--overflow:102%}svg {宽度:100%;高度:100%;垂直对齐:顶部}/*"fix"仍在顶部保留一个px线.并垂直拉伸SVG */svg {宽度:var(-overflow);高度:var(-overflow);溢出:可见;margin-top:0px;/* -1px至'fix'首行*/}</style>< div id = Tiles></div>< script>Tiles.innerHTML =`< my-tile></my-tile>`.repeat(100);customElements.define('my-tile',类扩展了HTMLElement {connectedCallback(){this.innerHTML =`< svg xmlns ="http://www.w3.org/2000/svg" viewBox ="0 0 8 8"> +'<矩形宽度='100%'高度='100%'填充='蓝色'/></svg>`;}});</script>  

更新2

将SO代码段的大小调整为较小的大小...现在Chrome也出错了

只剩下一个解决方法..计算像元宽度并四舍五入到整个像素...

解决方案

您将遇到舍入与抗锯齿陷阱:您的网格有10行10列,总宽度为504px.使用 repeat(1fr)调整大小意味着每个单元格的宽度为50.4像素.SVG调整为该值,并使用< rect> 填充整个视口.

这意味着嫁接元素的轮廓与完整像素不一致,并且每个方向上最外面的像素都具有部分透明度.

原则上,尝试使用 shape-rendering:crispEdges shape-rendering:geometricPrecision 来改善显示效果,但这并不能保证.但是,如果您将像素缩小50.4像素,或者至少在一侧具有抗锯齿效果,或者浏览器可能会在某些行或列上舍入像素数.

最终判决始终相同:

shape-rendering属性为实现提供了一个提示,即在渲染矢量图形元素时要进行哪些取舍...

提示不是规则.每个浏览器都可以实施自己的解决方案.

调整容器大小<​​/h3>

确保元素具有完整的像素大小是一种解决方案,并且应该始终是首选.如果每个尺寸的网格包含10个元素,则必须确保网格容器的尺寸始终是10像素的倍数.

但是,如果您希望网格能够做出响应,这可能会变得很复杂.只有媒体查询可以实现.(CSS calc() 函数仅接受四个基本运算符,不会舍入值.)

欺骗舍入功能

但是还有另一条路要走.相邻的< svg> 元素之间的某些重叠可以通过 overflow:visible 来实现,从而使 viewBox 之外的内容

SVGs take up 100% of the a CSS-Grid cell (with gap:0px)

JSFiddle at: https://jsfiddle.net/CustomElementsExamples/atgyz2s6/

But (only in Firefox!) sometimes a white gap is displayed:

  • The unwanted 'gap' shows the Grid background. (there is a gap:0px on the Grid!)

  • Setting shape-rendering:crispEdges makes it an even bigger gap.

  • Setting a fixed integer Grid width (columns * N) pixels 'fixes' the unwanted gap
    (but I can't use that, I have different Grid sizes, and use the available viewPort for the whole Grid)

  • Setting a background color on all Grid cells, does not display that gap line.

See JSFiddle (in FireFox): https://jsfiddle.net/CustomElementsExamples/atgyz2s6/

  • An extra <rect width='100%' wheight='100%' fill='blue'/> in each SVG does show extra more unwanted gaps.

  • there is also an extra line/gap on the right hand side of the grid.

Does it require an SVG or CSS Grid fix?

Update 1

.. fine in Chrome.

In FireFox red background lines are displayed. 102% overflow 'fix' from answer is applied on mouseover. (but this does stretch the SVG vertically)

<style>
  body {
    --width: 177px; /* simulating responsive error lines */
    --Xwidth: 180px; /* N x 10px 'fixes' the unwanted gaps */
    --overflow: 100%; /* see suggested 'fix' below */
    background: darkslategrey;
  }
  #Tiles {
    width: var(--width);height: var(--width);  
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    grid-template-rows: repeat(10, 1fr);
    gap: 0px; background: red;    /* should not be visible! */
    box-sizing: border-box;
    border: 2px solid yellow;
    overflow:hidden;
  }
  #Tiles:hover{ --overflow: 102%  }
  svg { width: 100%;height: 100%;  vertical-align: top  }
  /* "fix" still leaves one px line at the top. and stretches the SVG vertically */
  svg {
    width: var(--overflow);height: var(--overflow); overflow: visible;
    margin-top: 0px; /* -1px to 'fix' top line */
  }
</style>
<div id=Tiles></div>
<script>
  Tiles.innerHTML = `<my-tile></my-tile>`.repeat(100);
  customElements.define('my-tile', class extends HTMLElement {
    connectedCallback() {
      this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">` +
        `<rect width='100%' height='100%' fill='blue' /></svg>`;
    }
  });
</script>

Update 2

Resized the SO Snippet to smaller size... now Chrome goes wrong too

That leaves only one fix.. calculate cell-width and round to whole pixels...

解决方案

You are running into a rounding versus antialiasing trap: Your grid has 10 rows and ten columns, over a total width of 504px. Sizing with repeat(1fr) means each cell gets a width of 50.4px. The SVG gets sized to that value, with the <rect> filling the complete viewport.

This means that the outline of the grafical element does not coincide with full pixels, and the outermost pixel in each direction gets a partial transparency.

In principle, the attempt to improve the display with shape-rendering: crispEdges or shape-rendering: geometricPrecision might yield results, but that is not guaranteed. However you divy up 50.4px, either there can be at least one side with an antialiasing artefact, or the browser might round the number of pixels down on some rows or columns.

The end verdict is always the same:

The shape-rendering property provides a hint to the implementation about what tradeoffs to make as it renders vector graphics elements...

Hints are not rules. Every browser is at large to implement its own solution.

Sizing the container

Making sure elements have full pixel sizes is one solution, and should always be the first choice. If you have a grid of ten elements per dimension, you would have to make sure the grid container has always a multiple of 10px size.

But if you want your grid to be responsive, this might prove complicated. Only media queries can achieve that. (The CSS calc() function only accepts the four basic operators and will not round values.)

Cheating the rounding function

But there is also another way to go. Some overlap between neighbouring <svg> elements can be achieved with an overflow: visible, so that content outside the viewBox is not clipped, and increasing the area of rendered content. This does not change the computation of box sizes, it only means the implicit clip path surrounding the <svg> element is removed.

This obviously errs to the opposite side, and if it is critical that the outermost pixel is diplayed correctly, this might be just the wrong solution. But for your example, it improves the result.

The choosen size of the width of 102% is enough to cover 1px if the svg is diplayed on screen at a size of ~50px. Obviously, this value might be the wrong one for other scales, but that is the nature of drawing vector graphics onto a screen divided into pixels.

div {
  position: relative;
  height: 51px;
  width: 101px;
  margin: 20px;
  background: red;
}
svg {
  width: 50.4px;
  height: 50.4px;
}
rect {
  fill: blue;
}
path {
  stroke: white;
}
.overflowing svg {
  overflow: visible;
}

<div>
  <svg viewBox="0 0 8 8">
    <rect width='100%' height='100%' />
    <path d="M4 0v2"/><path d="M6 4h2"/>
    <path d="M4 6v2"/><path d="M0 4h2"/>
  </svg><svg viewBox="0 0 8 8">
    <rect width='100%' height='100%' />
    <path d="M4 0v2"/><path d="M6 4h2"/>
    <path d="M4 6v2"/><path d="M0 4h2"/>
  </svg><br/>
</div>
<div class="overflowing">
  <svg viewBox="0 0 8 8">
    <rect width='102%' height='102%' />
    <path d="M4 0v2"/><path d="M6 4h2"/>
    <path d="M4 6v2"/><path d="M0 4h2"/>
  </svg><svg viewBox="0 0 8 8">
    <rect width='102%' height='102%' />
    <path d="M4 0v2"/><path d="M6 4h2"/>
    <path d="M4 6v2"/><path d="M0 4h2"/>
  </svg>
</div>

这篇关于间隙为0px的CSS网格中的SVG显示背景颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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