使用CSS创建纯响应式 CSS 网格布局的英雄图片或横幅图片
友情提示:我只是个偶尔做开发的人,所以如果我做错了什么,请多多包涵 :-)。好了,文章继续……
最近我决定从零开始搭建自己的网站,目的是为了学习 Jekyll(一个支持博客的 Web 平台)和 GitHub Pages。我还想学习 SASS/SCSS。
我上一个真正意义上的网站在布局方面使用了div大量table的标签,还添加了一些 JavaScript 代码来管理所有元素。虽然网站整体看起来很棒,但任何改动都让我感到胆战心惊,打字时手指也酸痛不已。
在搭建网站之前,我决定先了解一下大家现在都用什么来编写 HTML 和 CSS 代码。正是在那时,我发现用 SASS 编程语言来编写样式表 (CSS) 非常有趣,SASS 本质上是一种更易读的 CSS。在学习 SASS 的过程中,我偶然发现了一些视频,这些视频大力宣传了使用 CSS Grid 进行响应式网站设计的优势。
在设计网站之前不久,我才第一次听说 CSS 网格,但意识到它们是对我div-table-javascript过去各种混搭风格的优雅实现后,我就被它征服了。
我的新网站决定 100% 基于 CSS Grid,并且不需要 JavaScript,而我也确实做到了(唯一的 JavaScript 是以与 Calendly、Mailchimp 等集成的形式出现的,但我没有为网站编写任何托管的 JavaScript 代码)。
但...
英雄图像/横幅图像死亡螺旋
你们肯定都见过这种设计。你访问一个网站,页面上会有一张大图片。这张图片会吸引你的注意力,让你注意到图片上方叠加的文字。这个文字层可能包含其他HTML元素,例如按钮或表单字段,比如用来订阅新闻简报的。由于图片可能会变化,而且文字可能难以辨认,你会注意到图片上有一个轻微的渐变效果。
我原以为创建这个东西会非常简单。放一个 CSS 网格布局,添加 HTML 代码,就大功告成了。结果并非如此。
如果你在所有地方(谷歌、YouTube、CodePen 等)搜索横幅图片或主图,你会看到设计师们创作它们的无数种方法。
有些代码示例非常复杂,需要用到 JavaScript。不过,大多数示例都采用一种方法,即先将文本放在页面上,无需添加图片。然后使用 CSS 将图片添加为背景图,在背景图上添加线性渐变,最后使用绝对定位将 HTML 叠加文本放置在页面上。
以下是我从 W3Schools 找到的一个简单的例子,但相信我,之后的情况会变得相当复杂。
这些方法固然不错,但我不想让它看起来像个临时拼凑的方案,比如用 CSS 添加背景图片、使用绝对定位来放置内容,或者用 JavaScript 来实现响应式布局。我想要的是一个纯 CSS 的 Grid 方案,但我找不到,所以在做了大量的研究之后,我决定自己写一个。
我的英雄形象要求
以下是我对主图的基本要求:
- 图片必须以
img标签的形式放置在 HTML 中。我不希望使用背景图片,也不希望图片在 CSS 中定义,而其他图片则在 HTML 中定义。 - 我希望所有主图/横幅图都能添加渐变叠加效果。
- HTML组件不能使用绝对定位。它们必须是响应式的,并且与CSS Grid兼容。
- 该横幅广告应该可以在 Firefox、Chrome、Edge 和 IE 浏览器上正常显示(至少在我测试过的 IE 版本上可以正常显示)。
解决方案
说实话,我一直很苦恼,因为市面上竟然没有一个简洁明了的网格布局方案,直到我发现了Sarah Edo 的 CSS Grid Generator。我尝试创建各种尺寸的网格,发现如果多次点击同一个网格区域,就会生成更多的网格区域。啊!原来网格区域可以重叠!
注:我后来将高度改为了固定的像素数。
我的全新 CSS 网格布局设计完成后,只需将每个元素依次堆叠即可。以下是网站的 3D 视图:
把所有东西整合起来
以下 CodePen 示例展示了最终解决方案。本文接下来的部分将带您逐步了解代码。
CodePen 使用了一张从Unsplash随机选择的图片。请注意,即使是横向或纵向的图片,大多数都能很好地显示……稍后会详细介绍。
html
我创建了一个 HTML 文件,并将以下代码放入其中body。其中包含一个section代表网格本身的 `<div>` 标签,以及三个分别div包含图像、渐变叠加层和内容的标签。在 CSS 中,这些divs被定义为网格区域,它们会相互重叠。
<!-- The CSS grid that makes up the entirety of the hero image/banner image area -->
<section class="top-banner-section">
<!-- The CSS grid area that displays the image (layer 1) -->
<div class="banner-image-div">
<img class="banner-image" src="https://source.unsplash.com/random" alt="Banner Image" />
</div>
<!-- The CSS grid area that displays the semi-transparent gradient overlay (layer 2) -->
<div class="banner-overlay-div"></div>
<!-- The CSS grid area that displays the content (layer 3) -->
<div class="banner-text-div">
<span class="banner-text">
<p class="banner-h1-text">Remain relevant in today's technology-driven economy</p>
<p class="banner-body-text">Learn how agile can give you a competitive edge.</p>
<p class="banner-btn"><a class="banner-btn-item" href="https://www.cambermast.com">Get started →</a></p>
</span>
</div>
</section>
CSS 网格系统
我使用了从前面提到的 CSS Grid 生成器中提取的 CSS Grid 代码,并对其进行了一些修改,将高度设置为 350px,并对其中包含的内容进行了对齐和两端对齐,使其居中显示。虽然我想要一个响应式网站,但我也对图片的最小尺寸做了一些限制。
如下面的代码片段所示,CSS Grid 与sectionHTML 代码中的相应元素“连接”在一起。
// Create three grid areas (boxes) that overlap each other, essentially creating three layers.
// Grid box 1 (layer 1): Image
// Grid box 2 (layer 2): Gradient overlay
// Grid box 3 (layer 3): Call to action text/content
.top-banner-section {
display: grid;
grid-template-columns: 1fr; // stretch to the full frame
grid-template-rows: 350px; // 350 pixels tall
grid-column-gap: 0px;
grid-row-gap: 0px;
align-content: center;
justify-content: center;
.banner-image-div {
grid-area: 1 / 1 / 2 / 2;
} // image
.banner-overlay-div {
grid-area: 1 / 1 / 2 / 2;
} // gradient or other overlay
.banner-text-div {
grid-area: 1 / 1 / 2 / 2;
} // overlay objects like text, buttons, etc.
}
此时,你已经有了创建包含三个网格区域的 CSS Grid 的 HTML 代码。可能不太明显的是,它是如何grid-area知道先显示图像、其次是渐变、最后是内容的。这取决于divHTML 中标签的顺序。所以,如果我把渐变div标签放在最前面,那么图像就会直接覆盖在渐变标签之上。
第一层:横幅图像
正如我在本文前面提到的,我希望横幅能够响应式设计。对于图片,我不会让它的最小尺寸小于 350 像素,因为那样字体会太小而难以辨认。否则,图片可能会铺满它所在的 CSS 网格的整个宽度和高度。
// Banner image (layer 1)
.banner-image {
display: grid;
min-width: 350px; // Do not resize to smaller than this.
width: 100%;
height: 100%;
object-fit: cover; // Using this so the image can be any size and still look halfway decent.
}
我一直想要但没在需求清单里明确列出的一个功能是:我的网格系统能够轻松处理我img在 HTML 标签里添加的任何图片。无论我放置的是大幅竖图还是横图,我都希望图片能显示正常。后来发现,用object-fit: cover;CSS 规则就能实现。基本原理是浏览器会按比例拉伸图片,并裁剪掉因高度和宽度限制而无法显示的部分。
为了使图片具有响应式设计,我将图片的宽度和高度都设置为 100%。这意味着随着浏览器窗口大小的变化,图片的高度和宽度也会随之变化。由于图片位于网格布局中,因此它永远不会大于其容器。
注意:我确信随意插入任何大小、宽度和高度的图像对优化和设计都是不利的,但这种使用对象适应的通用方法对我来说效果很好。
第二层:半透明渐变叠加层
正如以下代码所示,我在网上找到一个渐变生成器(有很多,我忘了记下我用的是哪个)。基本思路是创建一个从黑色到白色、角度为 60 度的线性渐变填充(为什么是 60 度?我觉得这样看起来不错)。
// Gradient overlay (layer 2)
// gradient overlay going from black to transparent.
// note: search for a gradient overlay generator to make this easier.
.banner-overlay-div {
display: grid;
max-width: 100%;
background: black;
background: linear-gradient(
60deg,
rgba(0, 0, 0, 0.7777485994397759) 30%,
rgba(255, 255, 255, 0) 100%
); // start at black at the bottom left'ish and goes at a 60% angle. This will make the white easy to read with nearly any image.
}
黑色区域 (0,0,0) 的透明度为 30%。白色区域 (255, 255, 255) 的透明度为 100%。通过设置这些透明度,既可以看到底层图像,又能更清晰地阅读图层 3 中显示的白色内容。
第三层:内容
此时,屏幕上会显示一张图片。图片上方是一层半透明的渐变图层。现在,我们要显示内容。正如你所看到的,我将内容居中放置,并在左右两侧留出一些边距,这样文字就不会紧贴图片边缘。
// Banner html components (layer 3)
// banner text
.banner-text-div {
display: grid;
align-items: center;
margin-left: 15px;
margin-right: 15px;
}
为了响应式设计,我本可以将尺寸设置margin-left为margin-right百分比、em、rem 或其他非硬编码的像素值,但这样对我来说已经足够了。
内容样式
既然我说过我的要求之一是让这个横幅广告具有响应式设计,那我就顺便说说我是如何格式化内容的。当然,这里使用的是 SASS,所以如果您想要的是 CSS 代码,请见谅。
我不会逐个讲解,但你可以看到我用了一个小calc技巧,比如“我不希望字体小于这个字号,但可以更大一些”。我很想知道大家对这种方法的好坏有什么看法,或者我是否应该采用其他方法,但总之,这种方法对我来说有效。
// Typograhy: *** This is all the stuff you change
.banner-h1-text {
// font can get larger, but no smaller than 10 points.
font-size: calc(10pt + 0.15vw);
letter-spacing: 0.05em;
font-weight: bolder;
text-transform: uppercase;
color: white;
}
.banner-body-text {
// font can get larger, but no smaller than 10 points.
font-size: calc(10pt + 0.15vw);
margin-top: 0.5em;
color: white;
text-decoration: none;
&:hover {
color: white;
}
&:visited {
color: white;
}
&:active {
color: white;
}
}
.banner-btn {
margin-top: 1em;
}
.banner-btn-item {
font-size: calc(8pt + 0.15vw); // responsive size, but keep a minimum.
padding-top: calc(0.5em + 0.08vw);
padding-bottom: calc(0.5em + 0.08vw);
padding-left: calc(0.5em + 0.08vw);
padding-right: calc(0.5em + 0.08vw);
color: blue;
background-color: white;
text-align: center;
text-transform: uppercase;
font-weight: bold;
border: 1px solid white;
&:link {
text-decoration: none;
}
&:visited {
text-decoration: none;
}
}
包起来
正如我在文章开头提到的,我并非全职程序员,但我喜欢学习。在开始这个项目之前,我甚至不知道 SASS 或 CSS Grid 的存在,但学习的过程确实很有趣。
我确信我做错了一些事情,以后可能会给我带来麻烦,但就目前而言,我进行的最少的浏览器测试表明,该网站运行良好。
如果您想查看仅使用 CSS Grid 的最终网站设计,请访问Cambermast.com查看。
欢迎并衷心感谢您对我的网站提出的任何修改建议,如果您愿意,请随时发送 pull request 或提交 issue。GitHub Pages 代码。
文章来源:https://dev.to/billraymond/creating-a-pure-responsive-css-grid-hero-image-or-banner-image-2pej


