整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          計(jì)育韜:照片過多,公眾號如何優(yōu)雅排版設(shè)計(jì)?

          計(jì)育韜:照片過多,公眾號如何優(yōu)雅排版設(shè)計(jì)?

          有些情況下,品牌、校園或政務(wù)官方公眾號需要羅列出大量的照片。如果素材出自專業(yè)攝影師之手,那么對運(yùn)營工作者尚且友善;如果照片畫質(zhì)參差不齊,則要面臨難以用統(tǒng)一設(shè)計(jì)語言調(diào)和的窘境……


          那么當(dāng)照片過多時(shí),到底有沒有好的方法能優(yōu)雅地完成公眾號排版?本期專題,計(jì)育韜老師通過親自交付的若干精彩案例和部分其他團(tuán)隊(duì)的優(yōu)秀作品,講授具體的素材設(shè)計(jì)、頁面布局與交互開發(fā)思路。



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


          《轉(zhuǎn)眼,就站在了2023年的最后一天。》


          企業(yè)年終總結(jié),往往涉及大量的照片展示。格蘭富公眾號在年底的《轉(zhuǎn)眼,就站在了2023年的最后一天。》中通過如以上的方式,將照片以不同的角度平鋪擺放。點(diǎn)擊后,一條線從刊物版面出發(fā),勾勒部分的照片細(xì)節(jié),并隨著圖文的展開持續(xù)前進(jìn)。


          在現(xiàn)實(shí)中,照片內(nèi)容本就各不相同,當(dāng)我們的設(shè)計(jì)越模擬真實(shí),讀者對照片的視覺統(tǒng)一性預(yù)期就越低。通過這種設(shè)計(jì)方式,原本略顯枯燥的照片與文案內(nèi)容反而更顯生動(dòng),并且通過線索的 SVG 運(yùn)動(dòng)呼應(yīng)了年度總結(jié)的主旨。


          在這篇 SVG 交互作品開發(fā)過程中,計(jì)育韜老師通過 <touchstart> - <click>的雙重觸發(fā)將軌跡描摹與畫布展開同時(shí)激活,值得一提的是此處還融入了「關(guān)懷設(shè)計(jì)」,即便用戶不做點(diǎn)擊行為,也會(huì)在若干秒后開始強(qiáng)制執(zhí)行動(dòng)畫,由此確保了企業(yè)中的中高層領(lǐng)導(dǎo)以及外籍人士等相對不熟悉 SVG 操作的讀者可以順利瀏覽內(nèi)容。

          《第一個(gè),宜昌!》


          我們也可以考慮在三維空間中,基于 perspective 3D 的 CSS 布局技術(shù),將照片以不同角度懸掛在開發(fā)者創(chuàng)建的公眾號坐標(biāo)系內(nèi)。正如三峽日報(bào)的《第一個(gè),宜昌!》中所呈現(xiàn)的照片群展。


          計(jì)育韜老師一般推薦perspective: 1px;空間尺度,同時(shí)注意在開發(fā)過程中,避免過于密集排列圖像進(jìn)而造成 iOS 渲染故障。



          方案二:宮格布局提升畫面故事性


          《牧馬人冬季低調(diào)創(chuàng)造》


          宮格是漫畫的通用載體,同樣也可以是公眾號排版的照片框架。如 JEEP 《牧馬人冬季低調(diào)創(chuàng)造》中的高清美圖就以宮格進(jìn)行布局,“無中生有”誕生了一段故事情節(jié),并通過彈出式海報(bào)支持用戶保存壁紙。在設(shè)計(jì)層面,車體采用了突破宮格的巧妙半摳圖設(shè)計(jì),且宮格線包含了不規(guī)則傾斜,靈動(dòng)而大氣,讓照片緊密卻不擁擠,豐富卻有重點(diǎn)。


          宮格布局的另一優(yōu)勢在于故事性(Storytelling)的強(qiáng)化可以對應(yīng)弱化讀者對照片視覺統(tǒng)一性的預(yù)期。體現(xiàn)故事進(jìn)程的照片可以用更真實(shí)的色彩還原現(xiàn)場體驗(yàn),我們以百威中國《點(diǎn)滴心意,水援千里》為例:


          《點(diǎn)滴心意,水援千里》


          路人「生圖」,尤其賑災(zāi)工作中的圖像資料品質(zhì)是尤其難把控的。從純設(shè)計(jì)層面來講,簡單平鋪只會(huì)傳遞出一種潦草敷衍的態(tài)度,造成適得其反的傳播結(jié)果。這種情況下設(shè)計(jì)師不妨通過宮格布局,結(jié)合文案設(shè)計(jì)提升畫面的故事感,讓照片轉(zhuǎn)化成一種親臨現(xiàn)場的感官憑證。



          方案三:照片風(fēng)格預(yù)處理


          《雖遲但到!看這條公眾號,你一定會(huì)笑笑笑笑!》


          使用相似的照片參數(shù)與濾鏡策略,即便是思政主題設(shè)計(jì),大量的照片也一樣可以美觀陳列。作為 E2.COOL 黑科技 SVG 編輯器第一屆 1024 節(jié)投稿大賽冠軍作品,西部空天的《雖遲但到!看這條公眾號,你一定會(huì)笑笑笑笑!》為廣大政務(wù)新媒體崗位同志做了極佳的示范。


          對融媒體工作而言,照片品質(zhì)可能是進(jìn)展延緩的原因,但必定不是作品粗糙的理由。在這里領(lǐng)域內(nèi),將海量照片美觀排版可以說是政務(wù)新媒體人的基本功之一。我們再以東線聯(lián)勤兵的《96年過去了,這支叫人民子弟兵的軍隊(duì)從未改變……》為例,這篇圖文的設(shè)計(jì)采用史料照片與 AIGC 人工智能生成相結(jié)合的方式,基于統(tǒng)一的黑白/做舊風(fēng)格進(jìn)行 perspective 3D 視差排版,歌頌了人民軍隊(duì) 96 年來的光輝歷史:




          方案四:在線數(shù)字展覽設(shè)計(jì)


          此前計(jì)育韜老師在《云 看 展,請 進(jìn) → → →》中,另外為廣大運(yùn)營人介紹了幾種在線表現(xiàn)大量照片畫面的優(yōu)雅排版策略,可以點(diǎn)擊藍(lán)色標(biāo)題重溫。這里額外推薦一個(gè) 3D 櫥窗型的 SVG 交互效果,最早由計(jì)育韜老師發(fā)明并授權(quán)于 E2.COOL 黑科技 SVG 編輯器作為模版呈現(xiàn),那就是「黑科技編輯器 | 視差相冊(縱向8圖)教程」模型。


          在小紅書的《起猛了,看見外灘同時(shí)升起200個(gè)月亮》中,這個(gè)模型充分實(shí)現(xiàn)了用戶投稿照片的優(yōu)雅展示:


          《起猛了,看見外灘同時(shí)升起200個(gè)月亮》


          更多行業(yè)頂尖 SVG 交互案例作品,歡迎移步 iSVG 公益免費(fèi)搜索引擎:http://www.isvg.com/


          第二屆中國 SVG 開發(fā)者大會(huì)很快將召開,這次除了行業(yè)各領(lǐng)軍開發(fā)者/團(tuán)隊(duì)外,如果你與計(jì)育韜老師曾在學(xué)術(shù)和項(xiàng)目層面有過深度交流,屆時(shí)也歡迎通過指定渠道報(bào)名參與。如有其他合作需求,請?zhí)砑游⑿牛篫huoya_Work 咨詢。




          -END-

          目中需要上傳圖片可謂是經(jīng)常遇到的需求,本文將介紹 3 種不同的圖片上傳方式,在這總結(jié)分享一下,有什么建議或者意見,請大家踴躍提出來。

          沒有業(yè)務(wù)場景的功能都是耍流氓,那么我們先來模擬一個(gè)需要實(shí)現(xiàn)的業(yè)務(wù)場景。假設(shè)我們要做一個(gè)后臺(tái)系統(tǒng)添加商品的頁面,有一些商品名稱、信息等字段,還有需要上傳商品輪播圖的需求。

          我們就以Vue、Element-ui,封裝組件為例子聊聊如何實(shí)現(xiàn)這個(gè)功能。其他框架或者不用框架實(shí)現(xiàn)的思路都差不多,本文主要聊聊實(shí)現(xiàn)思路。

          1.云儲(chǔ)存

          常見的 七牛云,OSS(阿里云)等,這些云平臺(tái)提供API接口,調(diào)用相應(yīng)的接口,文件上傳后會(huì)返回圖片存儲(chǔ)在服務(wù)器上的路徑,前端獲得這個(gè)路徑保存下來提交給后端即可。此流程處理相對簡單。

          主要步驟

          • 向后端發(fā)送請求,獲取OSS配置數(shù)據(jù)
          • 文件上傳,調(diào)用OSS提供接口
          • 文件上傳完成,后的文件存儲(chǔ)在服務(wù)器上的路徑
          • 將返回的路徑存值到表單對象中

          代碼范例

          我們以阿里的 OSS 服務(wù)來實(shí)現(xiàn),們試著來封裝一個(gè)OSS的圖片上傳組件。

          通過element-ui的upLoad組件的 http-request 參數(shù)來自定義我們的文件上傳,僅僅使用他組件的樣式,和其他上傳前的相關(guān)鉤子(控制圖片大小,上傳數(shù)量限制等)。

          <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' // 一個(gè)生產(chǎn)唯一的id的方法
           import OSS from 'ali-oss'
           
           export default {
           name: 'imgUpload',
           data () {
           return {}
           },
           methods: {
           // 圖片上傳前驗(yàn)證
           beforeAvatarUpload (file) {
           const isLt2M=file.size / 1024 / 1024 < 2
           if (!isLt2M) {
           this.$message.error('上傳頭像圖片大小不能超過 2MB!')
           }
           return isLt2M
           },
           // 上傳圖片到OSS 同時(shí)派發(fā)一個(gè)事件給父組件監(jiān)聽
           upload (item) {
           getAliOSSCreds().then(res=> { // 向后臺(tái)發(fā)請求 拉取OSS相關(guān)配置
           let creds=res.body.data
           let client=new OSS.Wrapper({
           region: 'oss-cn-beijing', // 服務(wù)器集群地區(qū)
           accessKeyId: creds.accessKeyId, // OSS帳號
           accessKeySecret: creds.accessKeySecret, // OSS 密碼
           stsToken: creds.securityToken, // 簽名token
           bucket: 'imgXXXX' // 阿里云上存儲(chǔ)的 Bucket
           })
           let key='resource/' + localStorage.userId + '/images/' + createId() + '.jpg' // 存儲(chǔ)路徑,并且給圖片改成唯一名字
           return client.put(key, item.file) // OSS上傳
           }).then(res=> {
           console.log(res.url)
           this.$emit('on-success', res.url) // 返回圖片的存儲(chǔ)路徑
           }).catch(err=> {
           console.log(err)
           })
           }
           }
           }
          </script>
          

          傳統(tǒng)文件服務(wù)器上傳圖片

          此方法就是上傳到自己文件服務(wù)器硬盤上,或者云主機(jī)的硬盤上,都是通過 formdata 的方式進(jìn)行文件上傳。具體的思路和云文件服務(wù)器差不多。

          主要步驟

          • 設(shè)置服務(wù)器上傳路徑、上傳文件字段名、header、data參數(shù)等
          • 上傳成功后,返回服務(wù)器存儲(chǔ)的路徑
          • 返回的圖片路徑存儲(chǔ)到表單提交對象中

          代碼示例

          此種圖片上傳根據(jù)element-ui的upLoad組件只要傳入后端約定的相關(guān)字段即可實(shí)現(xiàn),若使用元素js也是生成formdata對象,通過Ajax去實(shí)現(xiàn)上傳也是類似的。

          這里只做一個(gè)簡單的示例,具體請看el-upload組件相文檔就能實(shí)現(xiàn)

          <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' // 一個(gè)生產(chǎn)唯一的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) // 這里可以獲得上傳成功的相關(guān)信息
           }
           }
           }
          </script>
          

          圖片轉(zhuǎn) base64 后上傳

          有時(shí)候做一些私活項(xiàng)目,或者一些小圖片上傳可能會(huì)采取前端轉(zhuǎn)base64后成為字符串上傳。當(dāng)我們有這一個(gè)需求,有一個(gè)商品輪播圖多張,轉(zhuǎn)base64編碼后去掉data:image/jpeg;base64,將字符串以逗號的形勢拼接,傳給后端。我們?nèi)绾蝸韺?shí)現(xiàn)呢。

          1.本地文件如何轉(zhuǎn)成 base64

          我們通過H5新特性 readAsDataURL 可以將文件轉(zhuǎn)base64格式,輪播圖有多張,可以在點(diǎn)擊后立馬轉(zhuǎn)base64也可,我是在提交整個(gè)表單錢一次進(jìn)行轉(zhuǎn)碼加工。

          具體步驟

          • 新建文件封裝 異步 轉(zhuǎn)base64的方法
          • 添加商品的時(shí)候選擇本地文件,選中用對象保存整個(gè)file對象
          • 最后提交整個(gè)商品表單之前進(jìn)行編碼處理

          在這里要注意一下,因?yàn)?readAsDataURL 操作是異步的,我們?nèi)绾螌⒋嬖跀?shù)組中的若干的 file對象,進(jìn)行編碼,并且按照上傳的順序,把編碼后端圖片base64字符串儲(chǔ)存在一個(gè)新數(shù)組內(nèi)呢,首先想到的是promise的鏈?zhǔn)秸{(diào)用,可是不能并發(fā)進(jìn)行轉(zhuǎn)碼,有點(diǎn)浪費(fèi)時(shí)間。我們可以通過循環(huán) async 函數(shù)進(jìn)行并發(fā),并且排列順序。請看 methods 的 submitData 方法

          utils.js

          export function uploadImgToBase64 (file) {
           return new Promise((resolve, reject)=> {
           const reader=new FileReader()
           reader.readAsDataURL(file)
           reader.onload=function () { // 圖片轉(zhuǎn)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' // 導(dǎo)入本地圖片轉(zhuǎn)base64的方法
           
           export default {
           name: 'imgUpload',
           data () {
           return {
           diaLogForm: {
           goodsName:'', // 商品名稱字段
           imgBroadcastList:[], // 儲(chǔ)存選中的圖片列表
           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)
           }
           },
           // 有圖片移除后 觸發(fā)
           imgBroadcastRemove (file, fileList) {
           this.diaLogForm.imgBroadcastList=fileList
           },
           // 提交彈窗數(shù)據(jù)
           async submitDialogData () {
           const imgBroadcastListBase64=[]
           console.log('圖片轉(zhuǎn)base64開始...')
           // 并發(fā) 轉(zhuǎn)碼輪播圖片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('圖片轉(zhuǎn)base64結(jié)束..., ', imgBroadcastListBase64)
           this.diaLogForm.imgsStr=imgBroadcastListBase64.join()
           console.log(this.diaLogForm)
           const res=await addCommodity(this.diaLogForm) // 發(fā)請求提交表單
           if (res.status) {
           this.$message.success('添加商品成功')
           // 一般提交成功后后端會(huì)處理,在需要展示商品地方會(huì)返回一個(gè)圖片路徑 
           }
           },
           }
           }
          </script>
          

          這樣本地圖片上傳的時(shí)候轉(zhuǎn)base64上傳就完成了。可是輪播圖有可以進(jìn)行編輯,我們該如何處理呢?一般來說商品增加頁面和修改頁面可以公用一個(gè)組件,那么我們繼續(xù)在這個(gè)頁面上修改。

          編輯時(shí)我們首先會(huì)拉取商品原有數(shù)據(jù),進(jìn)行展示,在進(jìn)行修改,這時(shí)候服務(wù)器返回的圖片是一個(gè)路徑 http://xxx.xxx.xxx/abc.jpg 這樣,當(dāng)我們新增一張圖片的還是和上面的方法一樣轉(zhuǎn)碼即可。可是后端說,沒有修改的圖片也要賺base64轉(zhuǎn)過來,好吧那就做把。這是一個(gè)在線鏈接 圖片,不是本地圖片,怎么做呢?

          2. 在線圖片轉(zhuǎn)base64

          具體步驟

          utils.js 文件添加在線圖片轉(zhuǎn)base64的方法,利用canvas

          編輯商品,先拉取原來的商品信息展示到頁面

          提交表單之前,區(qū)分在線圖片還是本地圖片進(jìn)行轉(zhuǎn)碼

          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:[], // 儲(chǔ)存選中的圖片列表
           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)
           }
           },
           // 有圖片移除后 觸發(fā)
           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' 轉(zhuǎn)成[{url:'http://xxx.xxx.xx/j.jpg',...}] 這種格式在upload組件內(nèi)展示。 imgBroadcastList 展示原有的圖片
           this.diaLogForm.imgBroadcastList=this.diaLogForm.imgsStr.split(',').map(v=> ({ url: this.BASE_URL + '/' + v })) 
           }
           }).catch(err=> {
           console.log(err.data)
           })
           },
           // 提交彈窗數(shù)據(jù)
           async submitDialogData () {
           const imgBroadcastListBase64=[]
           console.log('圖片轉(zhuǎn)base64開始...')
           this.dialogFormLoading=true
           // 并發(fā) 轉(zhuǎn)碼輪播圖片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('圖片轉(zhuǎn)base64結(jié)束...')
           this.diaLogForm.imgs=imgBroadcastListBase64.join()
           console.log(this.diaLogForm)
           if (!this.isEdit) { // 新增編輯 公用一個(gè)組件。區(qū)分接口調(diào)用
           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>
          

          結(jié)語

          至此常用的三種圖片上傳方式就介紹完了,轉(zhuǎn)base64方式一般在小型項(xiàng)目中使用,大文件上傳還是傳統(tǒng)的 formdata或者 云服務(wù),更合適。但是 通過轉(zhuǎn)base64方式也使得,在前端進(jìn)行圖片編輯成為了可能,不需要上傳到服務(wù)器就能預(yù)覽。主要收獲還是對于異步操作的處理。

          最后

          以下是總結(jié)出來最全前端框架視頻,包含: javascript/vue/react/angualrde/express/koa/webpack 等學(xué)習(xí)資料。

          【領(lǐng)取方式】

          關(guān)注頭條 前端全棧架構(gòu)丶第一時(shí)間獲取最新前端資訊學(xué)習(xí)

          手機(jī)用戶可私信關(guān)鍵詞 【前端】即可獲取全棧工程師路線和學(xué)習(xí)資料!

          疊樣式表(Cascading Style Sheet,簡稱:CSS)是為網(wǎng)頁添加樣式的代碼。本節(jié)將介紹 CSS 的基礎(chǔ)知識(shí),并解答類似問題:怎樣將文本設(shè)置為黑色或紅色?怎樣將內(nèi)容顯示在屏幕的特定位置?怎樣用背景圖片或顏色來裝飾網(wǎng)頁?

          CSS 究竟什么來頭?

          和 HTML 類似,CSS 也不是真正的編程語言,甚至不是標(biāo)記語言。它是一門樣式表語言,這也就是說人們可以用它來選擇性地為 HTML 元素添加樣式。舉例來說,要選擇一個(gè) HTML 頁面里所有的段落元素,然后將其中的文本改成紅色,可以這樣寫 CSS:

          p {
            color: red;
          }

          不妨試一下:首先新建一個(gè) styles 文件夾,在其中新建一個(gè) style.css 文件,將這三行 CSS 保存在這個(gè)新文件中。

          然后再將該 CSS 文件連接至 HTML 文檔,否則 CSS 代碼不會(huì)對 HTML 文檔在瀏覽器里的顯示效果有任何影響。(如果你沒有完成前幾節(jié)的實(shí)踐,請復(fù)習(xí)處理文件 和 HTML 基礎(chǔ)。在筆記本里有這個(gè)方面的內(nèi)容!)

          1、打開 index.html 文件,然后將下面一行粘貼到文檔頭(也就是 <head></head> 標(biāo)簽之間)。

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

          2、保存 index.html 并用瀏覽器將其打開。應(yīng)該看到以下頁面:

          如果段落文字變紅,那么祝賀你,你已經(jīng)成功地邁出了 CSS 學(xué)習(xí)的第一步。

          “CSS 規(guī)則集”詳解

          讓我們來仔細(xì)看一看上述CSS:

          整個(gè)結(jié)構(gòu)稱為 規(guī)則集(通常簡稱“規(guī)則”),各部分釋義如下:

          • 選擇器(Selector
          • HTML 元素的名稱位于規(guī)則集開始。它選擇了一個(gè)或者多個(gè)需要添加樣式的元素(在這個(gè)例子中就是 p 元素)。要給不同元素添加樣式只需要更改選擇器就行了。
          • 聲明(Declaration
          • 一個(gè)單獨(dú)的規(guī)則,比如說 color: red; 用來指定添加樣式元素的屬性
          • 屬性(Properties
          • 改變 HTML 元素樣式的途徑。(本例中 color 就是 `` 元素的屬性。)CSS 中,由編寫人員決定修改哪個(gè)屬性以改變規(guī)則。
          • 屬性的值(Property value
          • 在屬性的右邊,冒號后面即屬性的值,它從指定屬性的眾多外觀中選擇一個(gè)值(我們除了 red 之外還有很多屬性值可以用于 color )。

          注意其他重要的語法:

          • 每個(gè)規(guī)則集(除了選擇器的部分)都應(yīng)該包含在成對的大括號里({})。
          • 在每個(gè)聲明里要用冒號(:)將屬性與屬性值分隔開。
          • 在每個(gè)規(guī)則集里要用分號(;)將各個(gè)聲明分隔開。

          如果要同時(shí)修改多個(gè)屬性,只需要將它們用分號隔開,就像這樣:

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

          多元素選擇

          也可以選擇多種類型的元素并為它們添加一組相同的樣式。將不同的選擇器用逗號分開。例如:

          p, li, h1 {
            color: red;
          }

          不同類型的選擇器

          選擇器有許多不同的類型。上面只介紹了元素選擇器,用來選擇 HTML 文檔中給定的元素。但是選擇的操作可以更加具體。下面是一些常用的選擇器類型:

          選擇器名稱

          選擇的內(nèi)容

          示例

          元素選擇器(也稱作標(biāo)簽或類型選擇器)

          所有指定(該)類型的 HTML 元素

          p 選擇 <p>

          ID 選擇器

          具有特定 ID 的元素(單一 HTML 頁面中,每個(gè) ID 只對應(yīng)一個(gè)元素,一個(gè)元素只對應(yīng)一個(gè) ID)

          #my-id 選擇 <p id="my-id"><a id="my-id">

          類選擇器

          具有特定類的元素(單一頁面中,一個(gè)類可以有多個(gè)實(shí)例)

          .my-class 選擇 <p class="my-class"><a class="my-class">

          屬性選擇器

          擁有特定屬性的元素

          img[src] 選擇 <img src="myimage.png"> 而不是 <img>

          偽(Pseudo)類選擇器

          特定狀態(tài)下的特定元素(比如鼠標(biāo)指針懸停)

          a:hover 僅在鼠標(biāo)指針懸停在鏈接上時(shí)選擇 <a>

          選擇器的種類遠(yuǎn)不止于此,更多信息請參閱 選擇器。

          字體和文本

          譯注:再一次說明,中文字體文件較大,不適合直接用于 Web Font。

          在探索了一些 CSS 基礎(chǔ)后,我們來把更多規(guī)則和信息添加至 style.css 中,從而讓示例更美觀。首先,讓字體和文本變得更漂亮。

          第一步:找到之前Google Font 輸出的地址。并以<link>元素的形式添加進(jìn)index.html文檔頭(<head></head>之間的任意位置)。代碼如下:

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

          以上代碼為當(dāng)前網(wǎng)頁下載 Open Sans 字體,從而使自定義 CSS 中可以對 HTML 元素應(yīng)用這個(gè)字體。

          第二步:接下來,刪除 style.css 文件中已有的規(guī)則。雖然測試是成功的了,但是紅字看起來并不太舒服。

          第三步:將下列代碼添加到相應(yīng)的位置,用你在 Google Fonts 找到的字體替代 font-family 中的占位行。( font-family 意味著你想要你的文本使用的字體。)這條規(guī)則首先為整個(gè)頁面設(shè)定了一個(gè)全局字體和字號(因?yàn)?<html> 是整個(gè)頁面的父元素,而且它所有的子元素都會(huì)繼承相同的 font-sizefont-family):

          html {
            /* px 表示 “像素(pixels)”: 基礎(chǔ)字號為 10 像素 */
            font-size: 10px;
            /* Google fonts 輸出的 CSS */
            font-family: 'Open Sans', sans-serif;
          }

          注:CSS 文檔中所有位于 /**/ 之間的內(nèi)容都是 CSS 注釋,它會(huì)被瀏覽器在渲染代碼時(shí)忽略。你可以在這里寫下對你現(xiàn)在要做的事情有幫助的筆記。

          譯注:/*``*/ 不可嵌套,/*這樣的注釋是/*不行*/的*/。CSS 不接受 // 注釋。

          接下來為文檔體內(nèi)的元素(<h1> (en-US)、<li><p>)設(shè)置字號。將標(biāo)題居中顯示,并為正文設(shè)置行高和字間距,從而提高頁面的可讀性。

             h1 {
               font-size: 60px;
               text-align: center;
             }
             
             p, li {
               font-size: 16px;
               /* line-height 后而可以跟不同的參數(shù),如果是數(shù)字,就是當(dāng)前字體大小乘上數(shù)字 */
               line-height: 2;
               letter-spacing: 1px;
             }

          可以隨時(shí)調(diào)整這些 px 值來獲得滿意的結(jié)果,以下是大體效果:

          一切皆盒子

          編寫 CSS 時(shí)你會(huì)發(fā)現(xiàn),你的工作好像是圍繞著一個(gè)一個(gè)盒子展開的——設(shè)置尺寸、顏色、位置,等等。頁面里大部分 HTML 元素都可以被看作若干層疊的盒子。



          并不意外,CSS 布局主要就是基于盒模型的。每個(gè)占據(jù)頁面空間的塊都有這樣的屬性:

          • padding:即內(nèi)邊距,圍繞著內(nèi)容(比如段落)的空間。
          • border:即邊框,緊接著內(nèi)邊距的線。
          • margin:即外邊距,圍繞元素外部的空間。



          這里還使用了:

          • width :元素的寬度
          • background-color :元素內(nèi)容和內(nèi)邊距底下的顏色
          • color :元素內(nèi)容(通常是文本)的顏色
          • text-shadow :為元素內(nèi)的文本設(shè)置陰影
          • display :設(shè)置元素的顯示模式(暫略)

          開始在頁面中添加更多 CSS 吧!大膽將這些新規(guī)則都添加到頁面的底部,而不要糾結(jié)改變屬性值會(huì)帶來什么結(jié)果。

          更改頁面顏色

          html{
            background-color:#00539f;
          }

          這條規(guī)則將整個(gè)頁面的背景顏色設(shè)置為 所計(jì)劃的顏色。

          文檔體格式設(shè)置

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

          現(xiàn)在是 <body> 元素。以上條聲明,我們來逐條查看:

          • width: 600px; —— 強(qiáng)制頁面永遠(yuǎn)保持 600 像素寬。
          • margin: 0 auto; —— 為 marginpadding 等屬性設(shè)置兩個(gè)值時(shí),第一個(gè)值代表元素的上方下方(在這個(gè)例子中設(shè)置為 0),而第二個(gè)值代表左邊右邊(在這里,auto 是一個(gè)特殊的值,意思是水平方向上左右對稱)。你也可以使用一個(gè),三個(gè)或四個(gè)值,參考 這里 。
          • background-color: #FF9500; —— 如前文所述,指定元素的背景顏色。我們給 body 用了一種略微偏紅的橘色以與深藍(lán)色的 `` 元素形成反差,你也可以嘗試其它顏色。
          • padding: 0 20px 20px 20px; —— 我們給內(nèi)邊距設(shè)置了四個(gè)值來讓內(nèi)容四周產(chǎn)生一點(diǎn)空間。這一次我們不設(shè)置上方的內(nèi)邊距,設(shè)置右邊,下方,左邊的內(nèi)邊距為20像素。值以上、右、下、左的順序排列。
          • border: 5px solid black; —— 直接為 body 設(shè)置 5 像素的黑色實(shí)線邊框。

          定位頁面主標(biāo)題并添加樣式

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

          你可能發(fā)現(xiàn)頁面的頂部有一個(gè)難看的間隙,那是因?yàn)闉g覽器會(huì)在沒有任何 CSS 的情況下 給 <h1>en-US等元素設(shè)置一些默認(rèn)樣式。但這并不是個(gè)好主意,因?yàn)槲覀兿M粋€(gè)沒有任何樣式的網(wǎng)頁也有基本的可讀性。為了去掉那個(gè)間隙,我們通過設(shè)置margin: 0;來覆蓋默認(rèn)樣式。

          至此,我們已經(jīng)把標(biāo)題的上下內(nèi)邊距設(shè)置為 20 像素,并且將標(biāo)題文本與 HTML 的背景顏色設(shè)為一致。

          需要注意的是,這里使用了一個(gè) text-shadow 屬性,它可以為元素中的文本提供陰影。四個(gè)值含義如下:

          • 第一個(gè)值設(shè)置水平偏移值 —— 即陰影右移的像素?cái)?shù)(負(fù)值左移)。
          • 第二個(gè)值設(shè)置垂直偏移值 —— 即陰影下移的像素?cái)?shù)(負(fù)值上移)。
          • 第三個(gè)值設(shè)置陰影的模糊半徑 —— 值越大產(chǎn)生的陰影越模糊。
          • 第四個(gè)值設(shè)置陰影的基色。

          不妨嘗試不同的值看看能得出什么結(jié)果。

          圖像居中

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

          最后,我們把圖像居中來使頁面更美觀。可以復(fù)用 body 的margin: 0 auto,但是需要一點(diǎn)點(diǎn)調(diào)整。<body>元素是塊級元素,意味著它占據(jù)了頁面的空間并且能夠賦予外邊距和其他改變間距的值。而圖片是內(nèi)聯(lián)元素,不具備塊級元素的一些功能。所以為了使圖像有外邊距,我們必須使用display: block 給予其塊級行為。

          注:以上說明假定所選圖片小于頁面寬度(600 pixels)。更大的圖片會(huì)溢出 body 并占據(jù)頁面的其他位置。要解決這個(gè)問題,可以:

          1)使用 圖片編輯器 來減小圖片寬度; 2)用 CSS 限制圖片大小,即減小 <img> 元素 width 屬性的值(比如 400 px)。

          注:如果你暫時(shí)不能理解 display: block 和塊級元素與行內(nèi)元素的差別也沒關(guān)系;隨著你對 CSS 學(xué)習(xí)的深入,你將明白這個(gè)問題。

          小結(jié)

          如果你按部就班完成本文的實(shí)踐,那么最終可以得到以下頁面


          相關(guān)推薦:

          前端新手看過來,手把手帶你輕松上手html的實(shí)操


          主站蜘蛛池模板: 亚洲AV本道一区二区三区四区| 日韩精品免费一区二区三区| 一本大道在线无码一区| 一区二区在线观看视频| 色久综合网精品一区二区| 人妻激情偷乱视频一区二区三区| 一区二区三区免费精品视频| 精品一区二区三区四区在线| 奇米精品一区二区三区在| 精品日韩亚洲AV无码一区二区三区| 国产精品一级香蕉一区| 人妻夜夜爽天天爽一区| 国产一区二区三区在线| 国产自产V一区二区三区C| 久久伊人精品一区二区三区| 亚洲午夜精品一区二区麻豆| 国产成人一区二区在线不卡| 精品国产一区二区三区久久蜜臀| 亚洲国产一区在线| 日本一区二区三区免费高清在线| 国产一区二区精品| 国产a久久精品一区二区三区| 性色av一区二区三区夜夜嗨| 国产一区二区三区亚洲综合| 日本亚洲成高清一区二区三区| 亚洲色无码专区一区| 蜜桃传媒视频麻豆第一区| 国产一区二区三区视频在线观看| 国产成人无码精品一区二区三区| 国产成人精品一区二三区熟女| 无码人妻久久一区二区三区免费| 美女视频黄a视频全免费网站一区| 成人精品视频一区二区三区不卡 | 白丝爆浆18禁一区二区三区| 国产AV一区二区三区传媒| 超清无码一区二区三区| 精品一区二区三区无码免费直播| 国产99久久精品一区二区| 亚洲一区二区中文| 麻豆AV一区二区三区久久| 久久综合九九亚洲一区|