整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

计育韬:照片过多,公众号如何优雅排版设计?

计育韬:照片过多,公众号如何优雅排版设计?

有些情况下,品牌、校园或政务官方公众号需要罗列出大量的照片。如果素材出自专业摄影师之手,那么对运营工作者尚且友善;如果照片画质参差不齐,则要面临难以用统一设计语言调和的窘境……


那么当照片过多时,到底有没有好的方法能优雅地完成公众号排版?本期专题,计育韬老师通过亲自交付的若干精彩案例和部分其他团队的优秀作品,讲授具体的素材设计、页面布局与交互开发思路。



方案一:让照片更具有「照片感」


《转眼,就站在了2023年的最后一天。》


企业年终总结,往往涉及大量的照片展示。格兰富公众号在年底的《转眼,就站在了2023年的最后一天。》中通过如以上的方式,将照片以不同的角度平铺摆放。点击后,一条线从刊物版面出发,勾勒部分的照片细节,并随着图文的展开持续前进。


在现实中,照片内容本就各不相同,当我们的设计越模拟真实,读者对照片的视觉统一性预期就越低。通过这种设计方式,原本略显枯燥的照片与文案内容反而更显生动,并且通过线索的 SVG 运动呼应了年度总结的主旨。


在这篇 SVG 交互作品开发过程中,计育韬老师通过 <touchstart> - <click>的双重触发将轨迹描摹与画布展开同时激活,值得一提的是此处还融入了「关怀设计」,即便用户不做点击行为,也会在若干秒后开始强制执行动画,由此确保了企业中的中高层领导以及外籍人士等相对不熟悉 SVG 操作的读者可以顺利浏览内容。

《第一个,宜昌!》


我们也可以考虑在三维空间中,基于 perspective 3D 的 CSS 布局技术,将照片以不同角度悬挂在开发者创建的公众号坐标系内。正如三峡日报的《第一个,宜昌!》中所呈现的照片群展。


计育韬老师一般推荐perspective: 1px;空间尺度,同时注意在开发过程中,避免过于密集排列图像进而造成 iOS 渲染故障。



方案二:宫格布局提升画面故事性


《牧马人冬季低调创造》


宫格是漫画的通用载体,同样也可以是公众号排版的照片框架。如 JEEP 《牧马人冬季低调创造》中的高清美图就以宫格进行布局,“无中生有”诞生了一段故事情节,并通过弹出式海报支持用户保存壁纸。在设计层面,车体采用了突破宫格的巧妙半抠图设计,且宫格线包含了不规则倾斜,灵动而大气,让照片紧密却不拥挤,丰富却有重点。


宫格布局的另一优势在于故事性(Storytelling)的强化可以对应弱化读者对照片视觉统一性的预期。体现故事进程的照片可以用更真实的色彩还原现场体验,我们以百威中国《点滴心意,水援千里》为例:


《点滴心意,水援千里》


路人「生图」,尤其赈灾工作中的图像资料品质是尤其难把控的。从纯设计层面来讲,简单平铺只会传递出一种潦草敷衍的态度,造成适得其反的传播结果。这种情况下设计师不妨通过宫格布局,结合文案设计提升画面的故事感,让照片转化成一种亲临现场的感官凭证。



方案三:照片风格预处理


《虽迟但到!看这条公众号,你一定会笑笑笑笑!》


使用相似的照片参数与滤镜策略,即便是思政主题设计,大量的照片也一样可以美观陈列。作为 E2.COOL 黑科技 SVG 编辑器第一届 1024 节投稿大赛冠军作品,西部空天的《虽迟但到!看这条公众号,你一定会笑笑笑笑!》为广大政务新媒体岗位同志做了极佳的示范。


对融媒体工作而言,照片品质可能是进展延缓的原因,但必定不是作品粗糙的理由。在这里领域内,将海量照片美观排版可以说是政务新媒体人的基本功之一。我们再以东线联勤兵的《96年过去了,这支叫人民子弟兵的军队从未改变……》为例,这篇图文的设计采用史料照片与 AIGC 人工智能生成相结合的方式,基于统一的黑白/做旧风格进行 perspective 3D 视差排版,歌颂了人民军队 96 年来的光辉历史:




方案四:在线数字展览设计


此前计育韬老师在《云 看 展,请 进 → → →》中,另外为广大运营人介绍了几种在线表现大量照片画面的优雅排版策略,可以点击蓝色标题重温。这里额外推荐一个 3D 橱窗型的 SVG 交互效果,最早由计育韬老师发明并授权于 E2.COOL 黑科技 SVG 编辑器作为模版呈现,那就是「黑科技编辑器 | 视差相册(纵向8图)教程」模型。


在小红书的《起猛了,看见外滩同时升起200个月亮》中,这个模型充分实现了用户投稿照片的优雅展示:


《起猛了,看见外滩同时升起200个月亮》


更多行业顶尖 SVG 交互案例作品,欢迎移步 iSVG 公益免费搜索引擎:http://www.isvg.com/


第二届中国 SVG 开发者大会很快将召开,这次除了行业各领军开发者/团队外,如果你与计育韬老师曾在学术和项目层面有过深度交流,届时也欢迎通过指定渠道报名参与。如有其他合作需求,请添加微信:Zhuoya_Work 咨询。




-END-

目中需要上传图片可谓是经常遇到的需求,本文将介绍 3 种不同的图片上传方式,在这总结分享一下,有什么建议或者意见,请大家踊跃提出来。

没有业务场景的功能都是耍流氓,那么我们先来模拟一个需要实现的业务场景。假设我们要做一个后台系统添加商品的页面,有一些商品名称、信息等字段,还有需要上传商品轮播图的需求。

我们就以Vue、Element-ui,封装组件为例子聊聊如何实现这个功能。其他框架或者不用框架实现的思路都差不多,本文主要聊聊实现思路。

1.云储存

常见的 七牛云,OSS(阿里云)等,这些云平台提供API接口,调用相应的接口,文件上传后会返回图片存储在服务器上的路径,前端获得这个路径保存下来提交给后端即可。此流程处理相对简单。

主要步骤

  • 向后端发送请求,获取OSS配置数据
  • 文件上传,调用OSS提供接口
  • 文件上传完成,后的文件存储在服务器上的路径
  • 将返回的路径存值到表单对象中

代码范例

我们以阿里的 OSS 服务来实现,们试着来封装一个OSS的图片上传组件。

通过element-ui的upLoad组件的 http-request 参数来自定义我们的文件上传,仅仅使用他组件的样式,和其他上传前的相关钩子(控制图片大小,上传数量限制等)。

<template>
 <el-upload
 list-type="picture-card"
 action="''"
 :http-request="upload"
 :before-upload="beforeAvatarUpload">
 <i class="el-icon-plus"></i>
 </el-upload>
</template>
 
<script>
 import {getAliOSSCreds} from '@/api/common' // 向后端获取 OSS秘钥信息
 import {createId} from '@/utils' // 一个生产唯一的id的方法
 import OSS from 'ali-oss'
 
 export default {
 name: 'imgUpload',
 data () {
 return {}
 },
 methods: {
 // 图片上传前验证
 beforeAvatarUpload (file) {
 const isLt2M=file.size / 1024 / 1024 < 2
 if (!isLt2M) {
 this.$message.error('上传头像图片大小不能超过 2MB!')
 }
 return isLt2M
 },
 // 上传图片到OSS 同时派发一个事件给父组件监听
 upload (item) {
 getAliOSSCreds().then(res=> { // 向后台发请求 拉取OSS相关配置
 let creds=res.body.data
 let client=new OSS.Wrapper({
 region: 'oss-cn-beijing', // 服务器集群地区
 accessKeyId: creds.accessKeyId, // OSS帐号
 accessKeySecret: creds.accessKeySecret, // OSS 密码
 stsToken: creds.securityToken, // 签名token
 bucket: 'imgXXXX' // 阿里云上存储的 Bucket
 })
 let key='resource/' + localStorage.userId + '/images/' + createId() + '.jpg' // 存储路径,并且给图片改成唯一名字
 return client.put(key, item.file) // OSS上传
 }).then(res=> {
 console.log(res.url)
 this.$emit('on-success', res.url) // 返回图片的存储路径
 }).catch(err=> {
 console.log(err)
 })
 }
 }
 }
</script>

传统文件服务器上传图片

此方法就是上传到自己文件服务器硬盘上,或者云主机的硬盘上,都是通过 formdata 的方式进行文件上传。具体的思路和云文件服务器差不多。

主要步骤

  • 设置服务器上传路径、上传文件字段名、header、data参数等
  • 上传成功后,返回服务器存储的路径
  • 返回的图片路径存储到表单提交对象中

代码示例

此种图片上传根据element-ui的upLoad组件只要传入后端约定的相关字段即可实现,若使用元素js也是生成formdata对象,通过Ajax去实现上传也是类似的。

这里只做一个简单的示例,具体请看el-upload组件相文档就能实现

<template>
 <el-upload
 ref="imgUpload"
 :on-success="imgSuccess"
 :on-remove="imgRemove"
 accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"
 :headers="headerMsg"
 :action="upLoadUrl"
 multiple>
 <el-button type="primary">上传图片</el-button>
 </el-upload>
</template>
 
<script>
 import {getAliOSSCreds} from '@/api/common' // 向后端获取 OSS秘钥信息
 import {createId} from '@/utils' // 一个生产唯一的id的方法
 import OSS from 'ali-oss'
 
 export default {
 name: 'imgUpload',
 data () {
 return {
 headerMsg:{Token:'XXXXXX'},
 upLoadUrl:'xxxxxxxxxx'
 }
 },
 methods: {
 // 上传图片成功
 imgSuccess (res, file, fileList) {
 console.log(res)
 console.log(file)
 console.log(fileList) // 这里可以获得上传成功的相关信息
 }
 }
 }
</script>

图片转 base64 后上传

有时候做一些私活项目,或者一些小图片上传可能会采取前端转base64后成为字符串上传。当我们有这一个需求,有一个商品轮播图多张,转base64编码后去掉data:image/jpeg;base64,将字符串以逗号的形势拼接,传给后端。我们如何来实现呢。

1.本地文件如何转成 base64

我们通过H5新特性 readAsDataURL 可以将文件转base64格式,轮播图有多张,可以在点击后立马转base64也可,我是在提交整个表单钱一次进行转码加工。

具体步骤

  • 新建文件封装 异步 转base64的方法
  • 添加商品的时候选择本地文件,选中用对象保存整个file对象
  • 最后提交整个商品表单之前进行编码处理

在这里要注意一下,因为 readAsDataURL 操作是异步的,我们如何将存在数组中的若干的 file对象,进行编码,并且按照上传的顺序,把编码后端图片base64字符串储存在一个新数组内呢,首先想到的是promise的链式调用,可是不能并发进行转码,有点浪费时间。我们可以通过循环 async 函数进行并发,并且排列顺序。请看 methods 的 submitData 方法

utils.js

export function uploadImgToBase64 (file) {
 return new Promise((resolve, reject)=> {
 const reader=new FileReader()
 reader.readAsDataURL(file)
 reader.onload=function () { // 图片转base64完成后返回reader对象
 resolve(reader)
 }
 reader.onerror=reject
 })
}

添加商品页面 部分代码

<template>
 <div>
 <el-upload
 ref="imgBroadcastUpload"
 :auto-upload="false" multiple
 :file-list="diaLogForm.imgBroadcastList"
 list-type="picture-card"
 :on-change="imgBroadcastChange"
 :on-remove="imgBroadcastRemove"
 accept="image/jpg,image/png,image/jpeg"
 action="">
 <i class="el-icon-plus"></i>
 <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2M</div>
 </el-upload>
 <el-button>submitData</el-button> 
 </div>
</template>
 
<script>
 import { uploadImgToBase64 } from '@/utils' // 导入本地图片转base64的方法
 
 export default {
 name: 'imgUpload',
 data () {
 return {
 diaLogForm: {
 goodsName:'', // 商品名称字段
 imgBroadcastList:[], // 储存选中的图片列表
 imgsStr:'' // 后端需要的多张图base64字符串 , 分割
 }
 }
 },
 methods: {
 // 图片选择后 保存在 diaLogForm.imgBroadcastList 对象中
 imgBroadcastChange (file, fileList) {
 const isLt2M=file.size / 1024 / 1024 < 2 // 上传头像图片大小不能超过 2MB
 if (!isLt2M) {
 this.diaLogForm.imgBroadcastList=fileList.filter(v=> v.uid !==file.uid)
 this.$message.error('图片选择失败,每张图片大小不能超过 2MB,请重新选择!')
 } else {
 this.diaLogForm.imgBroadcastList.push(file)
 }
 },
 // 有图片移除后 触发
 imgBroadcastRemove (file, fileList) {
 this.diaLogForm.imgBroadcastList=fileList
 },
 // 提交弹窗数据
 async submitDialogData () {
 const imgBroadcastListBase64=[]
 console.log('图片转base64开始...')
 // 并发 转码轮播图片list=> base64
 const filePromises=this.diaLogForm.imgBroadcastList.map(async file=> {
 const response=await uploadImgToBase64(file.raw)
 return response.result.replace(/.*;base64,/, '') // 去掉data:image/jpeg;base64,
 })
 // 按次序输出 base64图片
 for (const textPromise of filePromises) {
 imgBroadcastListBase64.push(await textPromise)
 }
 console.log('图片转base64结束..., ', imgBroadcastListBase64)
 this.diaLogForm.imgsStr=imgBroadcastListBase64.join()
 console.log(this.diaLogForm)
 const res=await addCommodity(this.diaLogForm) // 发请求提交表单
 if (res.status) {
 this.$message.success('添加商品成功')
 // 一般提交成功后后端会处理,在需要展示商品地方会返回一个图片路径 
 }
 },
 }
 }
</script>

这样本地图片上传的时候转base64上传就完成了。可是轮播图有可以进行编辑,我们该如何处理呢?一般来说商品增加页面和修改页面可以公用一个组件,那么我们继续在这个页面上修改。

编辑时我们首先会拉取商品原有数据,进行展示,在进行修改,这时候服务器返回的图片是一个路径 http://xxx.xxx.xxx/abc.jpg 这样,当我们新增一张图片的还是和上面的方法一样转码即可。可是后端说,没有修改的图片也要赚base64转过来,好吧那就做把。这是一个在线链接 图片,不是本地图片,怎么做呢?

2. 在线图片转base64

具体步骤

utils.js 文件添加在线图片转base64的方法,利用canvas

编辑商品,先拉取原来的商品信息展示到页面

提交表单之前,区分在线图片还是本地图片进行转码

utils.js

export function uploadImgToBase64 (file) {
 return new Promise((resolve, reject)=> {
 function getBase64Image (img) {
 const canvas=document.createElement('canvas')
 canvas.width=img.width
 canvas.height=img.height
 const ctx=canvas.getContext('2d')
 ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
 var dataURL=canvas.toDataURL()
 return dataURL
 }
 
 const image=new Image()
 image.crossOrigin='*' // 允许跨域图片
 image.src=img + '?v=' + Math.random() // 清除图片缓存
 console.log(img)
 image.onload=function () {
 resolve(getBase64Image(image))
 }
 image.onerror=reject
 })
}

添加商品页面 部分代码

<template>
 <div>
 <el-upload
 ref="imgBroadcastUpload"
 :auto-upload="false" multiple
 :file-list="diaLogForm.imgBroadcastList"
 list-type="picture-card"
 :on-change="imgBroadcastChange"
 :on-remove="imgBroadcastRemove"
 accept="image/jpg,image/png,image/jpeg"
 action="">
 <i class="el-icon-plus"></i>
 <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2M</div>
 </el-upload>
 <el-button>submitData</el-button> 
 </div>
</template>
 
<script>
 import { uploadImgToBase64, URLImgToBase64 } from '@/utils'
 
 export default {
 name: 'imgUpload',
 data () {
 return {
 diaLogForm: {
 goodsName:'', // 商品名称字段
 imgBroadcastList:[], // 储存选中的图片列表
 imgsStr:'' // 后端需要的多张图base64字符串 , 分割
 }
 }
 },
 created(){
 this.getGoodsData()
 },
 methods: {
 // 图片选择后 保存在 diaLogForm.imgBroadcastList 对象中
 imgBroadcastChange (file, fileList) {
 const isLt2M=file.size / 1024 / 1024 < 2 // 上传头像图片大小不能超过 2MB
 if (!isLt2M) {
 this.diaLogForm.imgBroadcastList=fileList.filter(v=> v.uid !==file.uid)
 this.$message.error('图片选择失败,每张图片大小不能超过 2MB,请重新选择!')
 } else {
 this.diaLogForm.imgBroadcastList.push(file)
 }
 },
 // 有图片移除后 触发
 imgBroadcastRemove (file, fileList) {
 this.diaLogForm.imgBroadcastList=fileList
 },
 // 获取商品原有信息
 getGoodsData () {
 getCommodityById({ cid: this.diaLogForm.id }).then(res=> {
 if (res.status) {
 Object.assign(this.diaLogForm, res.data)
 // 把 '1.jpg,2.jpg,3.jpg' 转成[{url:'http://xxx.xxx.xx/j.jpg',...}] 这种格式在upload组件内展示。 imgBroadcastList 展示原有的图片
 this.diaLogForm.imgBroadcastList=this.diaLogForm.imgsStr.split(',').map(v=> ({ url: this.BASE_URL + '/' + v })) 
 }
 }).catch(err=> {
 console.log(err.data)
 })
 },
 // 提交弹窗数据
 async submitDialogData () {
 const imgBroadcastListBase64=[]
 console.log('图片转base64开始...')
 this.dialogFormLoading=true
 // 并发 转码轮播图片list=> base64
 const filePromises=this.diaLogForm.imgBroadcastList.map(async file=> {
 if (file.raw) { // 如果是本地文件
 const response=await uploadImgToBase64(file.raw)
 return response.result.replace(/.*;base64,/, '')
 } else { // 如果是在线文件
 const response=await URLImgToBase64(file.url)
 return response.replace(/.*;base64,/, '')
 }
 })
 // 按次序输出 base64图片
 for (const textPromise of filePromises) {
 imgBroadcastListBase64.push(await textPromise)
 }
 console.log('图片转base64结束...')
 this.diaLogForm.imgs=imgBroadcastListBase64.join()
 console.log(this.diaLogForm)
 if (!this.isEdit) { // 新增编辑 公用一个组件。区分接口调用
 const res=await addCommodity(this.diaLogForm) // 提交表单
 if (res.status) {
 this.$message.success('添加成功')
 }
 } else {
 const res=await modifyCommodity(this.diaLogForm) // 提交表单
 if (res.status) {
 this.$router.push('/goods/goods-list')
 this.$message.success('编辑成功')
 }
 }
 }
 }
 }
</script>

结语

至此常用的三种图片上传方式就介绍完了,转base64方式一般在小型项目中使用,大文件上传还是传统的 formdata或者 云服务,更合适。但是 通过转base64方式也使得,在前端进行图片编辑成为了可能,不需要上传到服务器就能预览。主要收获还是对于异步操作的处理。

最后

以下是总结出来最全前端框架视频,包含: javascript/vue/react/angualrde/express/koa/webpack 等学习资料。

【领取方式】

关注头条 前端全栈架构丶第一时间获取最新前端资讯学习

手机用户可私信关键词 【前端】即可获取全栈工程师路线和学习资料!

叠样式表(Cascading Style Sheet,简称:CSS)是为网页添加样式的代码。本节将介绍 CSS 的基础知识,并解答类似问题:怎样将文本设置为黑色或红色?怎样将内容显示在屏幕的特定位置?怎样用背景图片或颜色来装饰网页?

CSS 究竟什么来头?

和 HTML 类似,CSS 也不是真正的编程语言,甚至不是标记语言。它是一门样式表语言,这也就是说人们可以用它来选择性地为 HTML 元素添加样式。举例来说,要选择一个 HTML 页面里所有的段落元素,然后将其中的文本改成红色,可以这样写 CSS:

p {
  color: red;
}

不妨试一下:首先新建一个 styles 文件夹,在其中新建一个 style.css 文件,将这三行 CSS 保存在这个新文件中。

然后再将该 CSS 文件连接至 HTML 文档,否则 CSS 代码不会对 HTML 文档在浏览器里的显示效果有任何影响。(如果你没有完成前几节的实践,请复习处理文件 和 HTML 基础。在笔记本里有这个方面的内容!)

1、打开 index.html 文件,然后将下面一行粘贴到文档头(也就是 <head></head> 标签之间)。

<link href="styles/style.css" rel="stylesheet">

2、保存 index.html 并用浏览器将其打开。应该看到以下页面:

如果段落文字变红,那么祝贺你,你已经成功地迈出了 CSS 学习的第一步。

“CSS 规则集”详解

让我们来仔细看一看上述CSS:

整个结构称为 规则集(通常简称“规则”),各部分释义如下:

  • 选择器(Selector
  • HTML 元素的名称位于规则集开始。它选择了一个或者多个需要添加样式的元素(在这个例子中就是 p 元素)。要给不同元素添加样式只需要更改选择器就行了。
  • 声明(Declaration
  • 一个单独的规则,比如说 color: red; 用来指定添加样式元素的属性
  • 属性(Properties
  • 改变 HTML 元素样式的途径。(本例中 color 就是 `` 元素的属性。)CSS 中,由编写人员决定修改哪个属性以改变规则。
  • 属性的值(Property value
  • 在属性的右边,冒号后面即属性的值,它从指定属性的众多外观中选择一个值(我们除了 red 之外还有很多属性值可以用于 color )。

注意其他重要的语法:

  • 每个规则集(除了选择器的部分)都应该包含在成对的大括号里({})。
  • 在每个声明里要用冒号(:)将属性与属性值分隔开。
  • 在每个规则集里要用分号(;)将各个声明分隔开。

如果要同时修改多个属性,只需要将它们用分号隔开,就像这样:

p {
  color: red;
  width: 500px;
  border: 1px solid black;
}

多元素选择

也可以选择多种类型的元素并为它们添加一组相同的样式。将不同的选择器用逗号分开。例如:

p, li, h1 {
  color: red;
}

不同类型的选择器

选择器有许多不同的类型。上面只介绍了元素选择器,用来选择 HTML 文档中给定的元素。但是选择的操作可以更加具体。下面是一些常用的选择器类型:

选择器名称

选择的内容

示例

元素选择器(也称作标签或类型选择器)

所有指定(该)类型的 HTML 元素

p 选择 <p>

ID 选择器

具有特定 ID 的元素(单一 HTML 页面中,每个 ID 只对应一个元素,一个元素只对应一个 ID)

#my-id 选择 <p id="my-id"><a id="my-id">

类选择器

具有特定类的元素(单一页面中,一个类可以有多个实例)

.my-class 选择 <p class="my-class"><a class="my-class">

属性选择器

拥有特定属性的元素

img[src] 选择 <img src="myimage.png"> 而不是 <img>

伪(Pseudo)类选择器

特定状态下的特定元素(比如鼠标指针悬停)

a:hover 仅在鼠标指针悬停在链接上时选择 <a>

选择器的种类远不止于此,更多信息请参阅 选择器。

字体和文本

译注:再一次说明,中文字体文件较大,不适合直接用于 Web Font。

在探索了一些 CSS 基础后,我们来把更多规则和信息添加至 style.css 中,从而让示例更美观。首先,让字体和文本变得更漂亮。

第一步:找到之前Google Font 输出的地址。并以<link>元素的形式添加进index.html文档头(<head></head>之间的任意位置)。代码如下:

 <link href="https://fonts.font.im/css?family=Open+Sans" rel="stylesheet" type="text/css"> 

以上代码为当前网页下载 Open Sans 字体,从而使自定义 CSS 中可以对 HTML 元素应用这个字体。

第二步:接下来,删除 style.css 文件中已有的规则。虽然测试是成功的了,但是红字看起来并不太舒服。

第三步:将下列代码添加到相应的位置,用你在 Google Fonts 找到的字体替代 font-family 中的占位行。( font-family 意味着你想要你的文本使用的字体。)这条规则首先为整个页面设定了一个全局字体和字号(因为 <html> 是整个页面的父元素,而且它所有的子元素都会继承相同的 font-sizefont-family):

html {
  /* px 表示 “像素(pixels)”: 基础字号为 10 像素 */
  font-size: 10px;
  /* Google fonts 输出的 CSS */
  font-family: 'Open Sans', sans-serif;
}

注:CSS 文档中所有位于 /**/ 之间的内容都是 CSS 注释,它会被浏览器在渲染代码时忽略。你可以在这里写下对你现在要做的事情有帮助的笔记。

译注:/*``*/ 不可嵌套,/*这样的注释是/*不行*/的*/。CSS 不接受 // 注释。

接下来为文档体内的元素(<h1> (en-US)、<li><p>)设置字号。将标题居中显示,并为正文设置行高和字间距,从而提高页面的可读性。

   h1 {
     font-size: 60px;
     text-align: center;
   }
   
   p, li {
     font-size: 16px;
     /* line-height 后而可以跟不同的参数,如果是数字,就是当前字体大小乘上数字 */
     line-height: 2;
     letter-spacing: 1px;
   }

可以随时调整这些 px 值来获得满意的结果,以下是大体效果:

一切皆盒子

编写 CSS 时你会发现,你的工作好像是围绕着一个一个盒子展开的——设置尺寸、颜色、位置,等等。页面里大部分 HTML 元素都可以被看作若干层叠的盒子。



并不意外,CSS 布局主要就是基于盒模型的。每个占据页面空间的块都有这样的属性:

  • padding:即内边距,围绕着内容(比如段落)的空间。
  • border:即边框,紧接着内边距的线。
  • margin:即外边距,围绕元素外部的空间。



这里还使用了:

  • width :元素的宽度
  • background-color :元素内容和内边距底下的颜色
  • color :元素内容(通常是文本)的颜色
  • text-shadow :为元素内的文本设置阴影
  • display :设置元素的显示模式(暂略)

开始在页面中添加更多 CSS 吧!大胆将这些新规则都添加到页面的底部,而不要纠结改变属性值会带来什么结果。

更改页面颜色

html{
  background-color:#00539f;
}

这条规则将整个页面的背景颜色设置为 所计划的颜色。

文档体格式设置

body{
   width:600px;
   margin:0 auto;
   background-color:#ff9500;
   padding:0 20px 20px 20px;
   border:5px solid black;
}

现在是 <body> 元素。以上条声明,我们来逐条查看:

  • width: 600px; —— 强制页面永远保持 600 像素宽。
  • margin: 0 auto; —— 为 marginpadding 等属性设置两个值时,第一个值代表元素的上方下方(在这个例子中设置为 0),而第二个值代表左边右边(在这里,auto 是一个特殊的值,意思是水平方向上左右对称)。你也可以使用一个,三个或四个值,参考 这里 。
  • background-color: #FF9500; —— 如前文所述,指定元素的背景颜色。我们给 body 用了一种略微偏红的橘色以与深蓝色的 `` 元素形成反差,你也可以尝试其它颜色。
  • padding: 0 20px 20px 20px; —— 我们给内边距设置了四个值来让内容四周产生一点空间。这一次我们不设置上方的内边距,设置右边,下方,左边的内边距为20像素。值以上、右、下、左的顺序排列。
  • border: 5px solid black; —— 直接为 body 设置 5 像素的黑色实线边框。

定位页面主标题并添加样式

h1{
  margin: 0;
  padding:20px 0;
  color: #00539f;
  text-shadow:3px 3px 1px black
}

你可能发现页面的顶部有一个难看的间隙,那是因为浏览器会在没有任何 CSS 的情况下 给 <h1>en-US等元素设置一些默认样式。但这并不是个好主意,因为我们希望一个没有任何样式的网页也有基本的可读性。为了去掉那个间隙,我们通过设置margin: 0;来覆盖默认样式。

至此,我们已经把标题的上下内边距设置为 20 像素,并且将标题文本与 HTML 的背景颜色设为一致。

需要注意的是,这里使用了一个 text-shadow 属性,它可以为元素中的文本提供阴影。四个值含义如下:

  • 第一个值设置水平偏移值 —— 即阴影右移的像素数(负值左移)。
  • 第二个值设置垂直偏移值 —— 即阴影下移的像素数(负值上移)。
  • 第三个值设置阴影的模糊半径 —— 值越大产生的阴影越模糊。
  • 第四个值设置阴影的基色。

不妨尝试不同的值看看能得出什么结果。

图像居中

img{
  display:block;
  margin:0 auto;
}

最后,我们把图像居中来使页面更美观。可以复用 body 的margin: 0 auto,但是需要一点点调整。<body>元素是块级元素,意味着它占据了页面的空间并且能够赋予外边距和其他改变间距的值。而图片是内联元素,不具备块级元素的一些功能。所以为了使图像有外边距,我们必须使用display: block 给予其块级行为。

注:以上说明假定所选图片小于页面宽度(600 pixels)。更大的图片会溢出 body 并占据页面的其他位置。要解决这个问题,可以:

1)使用 图片编辑器 来减小图片宽度; 2)用 CSS 限制图片大小,即减小 <img> 元素 width 属性的值(比如 400 px)。

注:如果你暂时不能理解 display: block 和块级元素与行内元素的差别也没关系;随着你对 CSS 学习的深入,你将明白这个问题。

小结

如果你按部就班完成本文的实践,那么最终可以得到以下页面


相关推荐:

前端新手看过来,手把手带你轻松上手html的实操