Coding猫

Coding猫 查看完整档案

无锡编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

Coding猫 赞了文章 · 10月27日

记一次前端"揭开绘制地图的神秘面纱"分享会

记一次前端"揭开绘制地图的神秘面纱"分享会

记录了我在组内的技术分享, 有同样需求的同学可以参考一下
分享全程下来时间大约 70分钟

image

一. 为什么要分享前端相关的"地图"知识

  1. (大屏展示)很多公司都会有相应的大屏幕展示系统, 例如中国或者全世界的客户与资产分布图.
  2. (生动描绘)用地图的角度来展示地理方面的关系, 让人看着比单纯的文字更直观
  3. (场景多)比如今年的各类疫情严重情况的分布图.
  4. 总的来说还是看起来比较炫酷, 可以提升一点点b格, 并且这个只是也是属于前端的范畴, 那么我们就有必要弄懂它.

二. 做地图相关技术简介

这里我只介绍几款我常用的

** 百度地图
这个名气太大了, 功能很多并且现在对3d的支持也很不错, 注意GL版v1.0 与之前 v2.0版本地图的api有点不一样别掉坑里.
缺点也比较明显, 比如你想要一份干干净净的地图, 上面没有店铺没有任何标识的时候我就建议你用echarts来玩了, 因为百度地图带的东西比较多.
想要使用百度地图的同学可以看这里, 超级简单就可以完成注册用玩耍.
使用非常简单

** hcharts
非常牛非常好用, 但是它部分功能是要收费的, 使用之前要让公司帮你买好相应的功能才能用于商用哦.
由于我们公司地图库是自己研发的最后也就没有这种网上付费的.
详情地址

** echarts
这个库前端无人不知了, 在需求很简单的情况下建议用这个技术来做, 大部分时候项目中需要绘制柱状图或折线图的时候已经引入了echarts此时不用重复引用来节省空间.
echarts画的地图

** 我们公司自己的2d, 3d地图组件库
这个在这里就不做过多详细介绍了, 一些公司也会有自主研发的地图组件, 设计的思想上可能与上面三个不太相同, 接下来我也会聊到.

三.echarts实现基础地图

以echarts为例是因为这个最好弄...

这里我新建了一个vue工程

<template>
  <div class="home">
    <div id="map"></div>
  </div>
</template>

<script>
import echarts from "echarts";
import mapData from "./geo";

export default {
  name: "Home",
  data() {
    return {
      myChart: null,
    };
  },
  methods: {
    initMap() {
      this.myChart = echarts.init(document.getElementById("map"));
      echarts.registerMap("world", mapData); // 定义名称下面要用, 这样做的好处就是可以很方便的实现切换地图的效果
      this.myChart.setOption({
        series: [
          {
            type: "map",
            mapType: "world", // 自定义扩展图表类型
            label: {
              show: false,
            },
          },
        ],
      });
    },
  },
  mounted() {
    this.initMap();
  }
};
</script>
  1. 像我们平时使用echarts一样先初始化
  2. 接下来有点不同需要echarts.registerMap("world", mapData); 可以理解为把这个数据命名为'world', 方便以后的切换(这里的数据我下面会讲).
  3. 在option的配置里面设置类型是地图, 使用上面定义好的'world'类型.

效果图
image

我们可以看得出来, 地图的绘制也没什么'特殊'的, 最主要的就是那个 mapData数据, 这个数据一般叫它geojson数据, 那么接下来我们认识一下它.

四.geojson数据到底是什么

  1. geojson是用json的语法表达和存储地理数据,可以说是json的子集, 它不是专门js使用的这点要清楚.
  2. 地图上有山川, 河流, 海洋等等的地理信息, 那么如何描述一条河? 这个时候就要使用geojson格式的文件来描绘.
  3. 并不是必须用geojson, geojson只是一套规范, 各大解析器用这套规范来解析生成对应的景色, 我们完全可以制定自己的规范来实现这些, 无非是兼容性不好需要自己写绘制的解析器.

五.geojson详细介绍

英语好的可以先撸网站
1. 基本结构

{ // 可以包括点线面, 一个大的集合
  "type": "FeatureCollection", // 定义这个是个geojson文件, 这里还可以是其他值下面会说
  "features": [] // 这里放要绘制的数据
}

以后我们看到"type": "FeatureCollection"这样一行就说明这个文件是geojson规范的文件

2. 描述一个点(Feature)
地图上的打点数据

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",  // 表示这个对象是一个要素
      "properties": {}, // 这里放样式, 后面会专门说
      "geometry": { // 这里面放具体的数据
        "type": "Point",  // 专指画点
        "coordinates": [105.380859375, 31.57853542647338] // 默认是经度与纬度, 三维的话就是xyz三个值, 当然这里也不一定是经纬度(不同的坐标体系)中会讲为什么
      }
    },
  ]
}

3. 描述多个点(FeatureCollection)
**优点

  1. 写法简洁
  2. 这些点样式可以共用
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "MultiPoint", // 多点, 也就是连续画多个同样的点
        "coordinates": [[105.380859375, 31.57853542647338],
        [105.580859375, 31.52853542647338]
        ]
      }
    },
  ]
}

4. 描述一条线(LineString)

  1. 这里还是描绘每一个点, 但这些点会连接在一起形成线
  2. 地图上的连线数据
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "LineString", // 这里所有的点会连接在一起形成线
        "coordinates": [[105.6005859375, 30.65681556429287],
        [107.95166015624999, 31.98944183792288],
        [109.3798828125, 30.031055426540206],
        [107.7978515625, 29.935895213372444]]
      }
    },
  ]
}

5. 描述多条线(MultiLineString)

  1. 这里第二组与第一组的线, 可以分隔开不会首尾相连.
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "MultiLineString",
        "coordinates":
          [
            [
              [105.6005859375, 30.65681556429287],
              [107.95166015624999, 31.98944183792288],
              [109.3798828125, 30.031055426540206],
              [107.7978515625, 29.935895213372444]
            ],
            [
              [109.3798828125, 30.031055426540206],
              [107.1978515625, 31.235895213372444]
            ]
          ]
      }
    },
  ]
}

6. 描述一个面(Polygon, 也叫多边形)

  1. 第一个点与最后一个点要相同, 这样才能完成闭环!!
  2. 三维数组的格式需要注意
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon", // 注意这里是三维数组
        "coordinates": [
          [
            [106.10595703125, 33.33970700424026],
            [106.32568359375, 32.41706632846282],
            [108.03955078125, 32.2313896627376],
            [108.25927734375, 33.15594830078649],
            [106.10595703125, 33.33970700424026]
          ]
        ]
      }
    },
  ]
}

7. 一个面里面有多个面(Polygon)

  1. 这种单一的'Polygon'里面出现多个形状, 会出现中空的情况, 类似布尔运算, 这样就可以在地图中描述那种圈型的国家
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -39.7265625,
              -3.162455530237848
            ],
            [
              127.96875,
              -3.162455530237848
            ],
            [
              127.96875,
              74.1160468394894
            ],
            [
              -39.7265625,
              74.1160468394894
            ],
            [
              -39.7265625,
              -3.162455530237848
            ]
          ],
          [
            [
              -22.5,
              15.961329081596647
            ],
            [
              110.74218749999999,
              15.961329081596647
            ],
            [
              110.74218749999999,
              70.8446726342528
            ],
            [
              -22.5,
              70.8446726342528
            ],
            [
              -22.5,
              15.961329081596647
            ]
          ]
        ]
      }
    }
  ]
}

效果如下:
image

8. 描述多个面(MultiPolygon)
优势:

  1. 写法简洁
  2. 这些点样式可以共用
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
          [
            [
              -39.7265625,
              -3.162455530237848
            ],
            [
              127.96875,
              -3.162455530237848
            ],
            [
              127.96875,
              74.1160468394894
            ],
            [
              -39.7265625,
              74.1160468394894
            ],
            [
              -39.7265625,
              -3.162455530237848
            ]
          ]
        ],
        [
          [
            [
              -22.5,
              15.961329081596647
            ],
            [
              110.74218749999999,
              15.961329081596647
            ],
            [
              110.74218749999999,
              70.8446726342528
            ],
            [
              -22.5,
              70.8446726342528
            ],
            [
              -22.5,
              15.961329081596647
            ]
          ]
        ]
        ]
      }
    }
  ]
}

这里如果重叠了就是颜色的叠加了如图所示:
image

9. 描述一个组(geometries)

  1. 比如我们为了表示一种特定的地貌那么我们可以把这个地貌数据独立起来
{
  "type": "FeatureCollection",
  "features": [
    { // 可以包括点线面, 一个独立的集合
      "type": "GeometryCollection",
      "geometries": [
        {
          "type": "Point",
          "coordinates": [108.62, 31.02819]
        }, {
          "type": "LineString",
          "coordinates": [[108.896484375, 30.1071178870],
          [108.2184375, 30.91717870],
          [109.5184375, 31.2175780]]
        }
      ]
    }
  ]
 }

10. 不同的样式(properties)

{
  "type": "FeatureCollection",
  "features": [
     {
      "type": "Feature",
      "properties": { // 专门放属性
        "stroke": "#fa9661", // 外边颜色
        "stroke-width": 4.1, // 外边宽
        "stroke-opacity": 0.7, // 外边透明度
        "fill": "#9e290c",  // 填充色
        "fill-opacity": 0.7 // 填充色透明度
      },
      "geometry": {
        "type": "Point",  // 画点
        "coordinates": [105.380859375, 31.57853542647338]
      }
    },
  ]
}

六. geojson的相关网站与工具的使用

** 展示干巴巴的数据大家看着不起劲, 这里我推荐一个绘制geojson的超棒网站地址

那么我来介绍一下如何使用这个网站高效的生成, 以及调试geojson
image

  1. 也就是最后生成的geojson, 这里的变化可以实时影响图像, 并且会有错误提示很方便编写.
  2. 绘制直线
  3. 绘制多边形也就是面, 这里注意要首位相连.
  4. 绘制矩形, 这里应该是专门封装的方法绘制矩形.
  5. 绘制点, 这里会为我们在地图上mark一下, 具体的图片需要我们自己在项目中引用.

image

  1. 点击之后进入编辑模式, 鼠标在图形上会出现小手标识, 此时可以拖动图形移动, 操作可以选择是否保留.
  2. 删除模式, 点击可以删除指定图形,操作可以选择是否保留.

image
单击图形可以出现如图所示的操作框.

  1. 添加样式属性, 上方展示的是当前样式属性
  2. 保存你的更改
  3. 删除这个图形

image

  1. 点击open可以使用本地的geojson文件进行导入绘制.
  2. save下面点击geojson可以把生成的代码文件下载到本地.

七.自制geojson解析绘制工具的思路

  1. 我们可以只做一个转换器, 也就是你随便写认为不错的格式, 最后转换成geojson的格式.
  2. 直接用你喜欢的格式来绘制图形
  3. 如果用canvas来实现就是绘制对应的图形就好了, 就是图形叠加那里需要特殊处理一下, 样式直接读取properties里面的数据进行设置.
  4. 绘制经纬度也是个问题, 毕竟在平面上不好计算经纬度(接下地图绘制章节会讲相关知识).
  5. 所以综上看来是不是绘制一张平面版的地图也没那么困难, 只要数据对了就成功一小半了.

八.地图的基本概念 (瓦片地图, 矢量地图)

** 有没有发现咱们使用的地图在放大的时候,区域都是一个方块一个方块的被加载成图像的.
** 如果你打开控制台的network还可以看到有好多png的请求.
** 地图这种超大的数据, 超多细节是如何做到快速渲染的?
** 下面是现在比较主流的两种地图的绘制模式.

栅格瓦片地图

顾名思义图片像是瓦片一样堆叠起来的格子状成为地图, 有点像拼图, 是不是感觉一点也不高大上....
但这里也是有很多问题要解决的, 比如你在俯视世界的视角看地图, 那么出现的就是世界的瓦片图片, 当高度小于一定的数值时就采用另一套相应的瓦片, 在某个高度范围内是采用放大瓦片图片的方式模拟视野的下降, 每次请求瓦片图片都需要传递: 1: 当前视口所在坐标(经纬度) 2: 当前视口宽高 3: 当前视角高度.

栅格瓦片以 256 256 或 512 512 大小的图片为介质,这种技术通常是在服务端预先将图片渲染好,前端根据地图的缩放等级,按需加载图片加以拼接,目前依旧在大规模使用,但这种方式存在一些劣势:

受到网络带宽开销和存储空间限制的影响大,离线化部署成本高,单套主题将近 500 多 G(中国)。
样式编辑完后端渲染需要时间长。
无三维的建筑数据,在 3D 场景中无高度信息。
数据保密性差。

矢量地图

顾名思义就是矢量绘制出图形, 只要不是照片肯定会小很多, 对于矢量为什么轻量并且不失真可以参考的上篇文章svg的分享svg实战

矢量瓦片采用和栅格瓦片相同的分级切割方案,不同的是,瓦片数据传输的是地理数据,包括道路、土地、建筑等,通过在前端做地图的渲染,具有如下优势:

极少占用服务器空间,降低网络开销,本地化部署只需5G空间(中国)。
地图的底图样式更换简单.
因为具有了地理数据本身,可在数据基础上做三维空间的延伸,例如 3D 建筑。
数据保密性强。

九.不同的坐标系

** 地球本身是个椭球体, 要把它以平面的方式绘制在一个矩形上也真的不好办, 现在有不少绘制的方式但是都有各自的优缺点, 感兴趣的朋友可以查查看具体的细节, 我这里就简单介绍下比较常见的方式.

  1. 经纬度EPSG:4326 也就是地图的默认坐标
    现在球体上定义好经纬度, 然后在正方形纸上画出刻度, 对应的绘制
  2. 墨卡托投影(EPSG:3785 )
    把地球放在一个圆筒里面, 假设地球内部有个光源, 那么地球在圆柱上的投影就是地图
  3. 火星坐标系

火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地图、导航设备都是采用的这一坐标系或在这一坐标的基础上进行二次加密得到的。
火星坐标的真实名称应该是 GCJ-02 坐标,基本上所有的国内的电子地图采用的都是火星坐标系甚至 Google 地图中国部分都特意为中国政府做了偏移。

  1. 百度坐标系

火星坐标是在国际标准坐标 WGS-84 上进行的一次加密,由于国内的电子地图都要至少使用火星坐标进行一次加密,百度直接就任性一些,直接自己又研究了一套加密算法,来了个 二次加密,这就是我们所熟知的百度坐标 BD-09,当然只有百度地图使用的是百度坐标

  1. WGS-84 坐标系

GS-84 坐标是一个国际的标准,一般卫星导航,原始的 GPS 设备中的数据都是采用这一坐标系。国外的 GoogleMap、OpenStreetMap、MapBox、OpenLayer 等采用的都是这一坐标。

geojson设置坐标系
由于坐标系的不同, 那么就算绘制一个点的坐标也都不会完全相同了, 那么就需要我们来告诉使用geojson的人按哪种坐标系进行解析

{
  "type": "FeatureCollection",
  "crs": { // 定义坐标系 (如果不写就是使用经纬度的坐标系)   默认为EPSG:4326。
    "type": "name", // "type" 和 "properties"。为强制拥有
    "properties": {
      "name": "urn: ogc: def: crs: EPSG: 54013" // 这里定义具体的规则
    }
  },
  "features": [
     {},
  ]
}

使用上线的规则

{
  "type": "FeatureCollection",
  "crs": {
    "type": "link", // 这里变成了link
    "properties": {
      "href": "http://example.com/crs/42", // 这里是你设置的资源链接
      "type": "proj4" // "proj4","ogcwkt",esriwkt" 只能这三种格式
    }
  },
  "features": [
     {},
  ]
}

十.更快的前端数据 -> WebAssembly

**WebAssembly是一种新的编码方式,文件体积更小,启动速度更快,运行速度也更快,与使用JavaScript构建的Web应用相比,性能提升明显。它是多种编程语言的编译器目标,包括C++、C、Rust等。
WebAssembly 是由主流浏览器厂商组成的 W3C 社区团体 制定的一个新的规范。**

WebAssembly 可以明显的提升计算的速率, 还挺适合用在地图库里面的

  1. WebAssembly 和 JavaScript 结合使用, 短时间并不会替代js
  2. .wasm文件结尾的文件来标识.
  3. WebAssembly 有一套完整的语义,实际上 wasm 是体积小且加载快的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率
    WebAssembly 运行在一个沙箱化的执行环境中,甚至可以在现有的 JavaScript 虚拟机中实现。在web环境中,WebAssembly将会严格遵守同源策略以及浏览器安全策略。
    WebAssembly 设计了一个非常规整的文本格式用来、调试、测试、实验、优化、学习、教学或者编写程序。可以以这种文本格式在web页面上查看wasm模块的源码。
    WebAssembly 在 web 中被设计成无版本、特性可测试、向后兼容的。WebAssembly 可以被 JavaScript 调用,进入 JavaScript 上下文,也可以像 Web API 一样调用浏览器的功能。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。
  4. 解析 - 解码 WebAssembly 比解析 JavaScript 要快

编译和优化 - 编译和优化所需的时间较少,因为在将文件推送到服务器之前已经进行了更多优化,JavaScript 需要为动态类型多次编译代码
重新优化 - WebAssembly 代码不需要重新优化,因为编译器有足够的信息可以在第一次运行时获得正确的代码
执行 - 执行可以更快,WebAssembly 指令更接近机器码
垃圾回收 - 目前 WebAssembly 不直接支持垃圾回收,垃圾回收都是手动控制的,所以比自动垃圾回收效率更高。目前浏览器中的 MVP(最小化可行产品) 已经很快了。在接下来的几年里,随着浏览器的发展和新功能的增加,它将在未来几年内变得更快。

说了这些都是概念, 接下来我们就一起实战一下go

十一. hello 级别的WebAssembly

中文官网
官网的实现还需要配置环境啥的搞得很正式, 入门级别其实我们更想的是尝尝鲜, 只要你会点c++就能用我接下来的方法实现.

在线生成
在线生成

image

  1. 点击转换c++代码为WebAssembly格式
  2. 点击下载转换好的文件
  3. 下载到的是个二进制文件

引用文件

    fetch("/test.wasm")
      .then((res) => res.arrayBuffer()) // 拿到Buffer格式
      .then((bytes) => WebAssembly.compile(bytes)) // 转字节码
      .then((mod) => {
        const instance = new WebAssembly.Instance(mod);
        const exp = instance.exports;
        console.log(exp._Z7showNumv())
      });
  1. exp._Z7showNumv 而不是 exp.showNum, 这个我们可以在Wat那一栏修改一下, 但是代码多了修改起来也不容易应该有禁止转换时修改名称的选项这里就不过多展开了.
  2. 注意这里会跨域, 因为属于文件协议, 你可以本地启个服务.

开发成本

  1. 需要的不只是前端技术了.
  2. bug稍微有点多, 比如不好调试, 还有的同学遇到了每次编译结果不同等问题.
  3. 社区不完善
  4. 建议这门技术先使用在封装度较高, 计算量很大的模块上.

十二.(组内篇)我写的2d与3d工程的代码介绍

这里我在组内展示一下我编写的两个项目的代码结构与遇到的问题, 就不在这里展开了毕竟涉及保密问题, 但大体思路就是把地图分成世界, 国家, 省, 市, 区 几个等级(省市区是中国的分法), 相当于一个状态机, 然后在每个状态下做相应的事比如打点与连线, 每次变换图层状态都会隐藏其他图层展示相应视野的图层.

end.

地图方面也属于前端比较有用的一环, 我今年刚接触地图相关项目也是一脸蒙, 但是详细学习了geojson等知识之后再用地图相关组件库就非常顺畅了.
这次就是这样, 希望和你一起进步.

查看原文

赞 14 收藏 10 评论 1

Coding猫 发布了文章 · 9月19日

css页面布局--瀑布流布局

首先我们看下,什么叫瀑布流?

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

比如下面这个网站,便是瀑布流布局:

image

使用column-count和column-gap来实现瀑布流布局(适合简单的瀑布流排版)

body {
  margin: 4px;
  font-family: Arial, Helvetica, sans-serif;
}

.masonry {
  column-count: 4;
  column-gap: 0;
}

.item {
  padding: 2px;
  position: relative;
  counter-increment: count;
}

.item img {
  display: block;
  width: 100%;
  height: auto;
}

.item::after {
  position: absolute;
  display: block;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  text-align: center;
  line-height: 24px;
  background-color: #000;
  color: #fff;
  content: counter(count);
}
<body>
    <div class="masonry">
        <div class="item">
            <img data-original="https://picsum.photos/360/460?radom=1" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/520?radom=2" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/420?radom=3" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/500?radom=4" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/420?radom=5" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/460?radom=6" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/480?radom=7" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/460?radom=8" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/420?radom=9" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/500?radom=10" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/460?radom=11" alt="">
        </div>
        <div class="item">
            <img data-original="https://picsum.photos/360/360?radom=12" alt="">
        </div>
    </div>
</body>

image

不足之处:

图片顺序是从上到下排列。如果你的网页是要按照时间倒序来展示照片,那么,我们就需要照片先从左至右排列,在换行,所以目前这种方式虽然简单,但是很多场景中不适合使用。

flexBox方式实现瀑布流布局(不推荐)

我们还是使用刚才的html格式,css布局方式改成flex布局。
关于flex布局可以看我另一篇文章:Flex布局
如果我们将flex容器的高度设置为1000px固定高度,且flex-direction设置为colunm方式,那么,当高度无法容纳所有图片时候,在flex-wrap: wrap的情况下,多余的图片变会在主轴方向换行。如下图所示:

body {
  margin: 4px;
  font-family: Arial, Helvetica, sans-serif;
}

.masonry {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 1000px;


}

.item {
  position: relative;
  width: 25%;
  padding: 2px;
  counter-increment: count;
}

.item img {
  display: block;
  width: 100%;
  height: auto;
}

.item::after {
  position: absolute;
  display: block;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  text-align: center;
  line-height: 24px;
  background-color: #000;
  color: #fff;
  content: counter(count);
}

image

但是,这里会发现我们展示的图片排序也是自上而下的顺序排序。

但是在flex中,我们可以使用order值来改变图片顺序,从而满足有从左至右排序的要求,代码如下:

/**因为column为主轴,那么我们就规定第1,5,9张照片顺序优先,在主轴,也就是纵列先展示,
2,6,10张照片在第二列展示,以此类推,这里用了数学方式取了个巧**/
.item:nth-child(4n+1) {
  order: 1;
}

.item:nth-child(4n+2) {
  order: 2;
}

.item:nth-child(4n+3) {
  order: 3;
}

.item:nth-child(4n+4) {
  order: 4;
}

image

此时,网页便如图效果。

不足之处:

我们如果缩放浏览器宽度:

image

由于flex的容量的高度是固定的,这时候缩小容器的宽度,而容器内的图片高度又因为宽度而改变(图片宽度设置成width: 100%),这时候flex只需要分成两列,便可以容纳所有图片,而我们只是用了数学方式来取巧规定了顺序,而交叉轴宽度变小,打乱了原先布局,能那么这时候图片顺序又会被打乱。便会如上图效果。

第三方插件实现瀑布流(推荐)

在这里,我是比较推荐使用第三方插件来实现瀑布流布局的。

我这里使用masonry来举例

→→→→→masonry官网←←←←←

按照官网介绍来看下:

Masonry is a JavaScript grid layout library. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall. You’ve probably seen it in use all over the Internet.

大概意思是Masonry是个第三方布局插件,让你变得像个堆砌砖墙的工匠一样,把空间里的元素放置在最佳的位置。有点难以理解吧,我们直接上代码。

<script data-original="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script data-original="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>

这里我们用CDN方式引入jquery和masony插件。

下面是我写的css代码

body {
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica, sans-serif;
}

.grid-item {
  position: relative;
  width: 25%;
  border: 2px solid hsla(0, 0%, 0%, 0.5);
  box-sizing: border-box;
  counter-increment: count;
}


.grid-item img {
  display: block;
  height: auto;
  width: 100%;
}


.grid-item::after {
  position: absolute;
  display: block;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  text-align: center;
  line-height: 24px;
  background-color: #000;
  color: #fff;
  content: counter(count);
}
<body>
  <div class="grid">
    <!-- 第一行 -->
    <div class="grid-item">
      <img data-original="./img/1.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/2.jpg" alt="">
    </div>
    <div class=" grid-item">
      <img data-original="./img/3.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/4.jpg" alt="">
    </div>
    <!-- 第二行 -->
    <div class="grid-item">
      <img data-original="./img/5.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/6.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/7.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/8.jpg" alt="">
    </div>
    <!-- 第三行 -->
    <div class="grid-item">
      <img data-original="./img/9.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/10.jpg" alt="">
    </div>

    <div class="grid-item ">
      <img data-original="./img/11.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/12.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/13.jpg" alt="">
    </div>
    <div class="grid-item">
      <img data-original="./img/14.jpg" alt="">
    </div>

  </div>
</body>

我把每个照片都宽度设置成了25%。也就是在每行会呈现4张照片。接下来是js代码

var $grid = $('.grid').masonry({
  itemSelector: '.grid-item', 
  percentPosition: true, //使用百分比宽度的响应式布局
  horizontalOrder: true, //对项目进行布局以保持水平的从左到右的顺序,定义了此条件,照片一般会按照从左到右顺序排列,但也不是绝对的。
  originLeft: true, //设置布局方式为从左到右,此项是默认值,可以不填写,如果你设置值为false,则会从右到左排序
  originTop: true,//设置布局方式为从上到下,此项是默认值,可以不填写,如果你设置值为false,则会从下到上排序
  transitionDuration: '0.8s',//更改位置或外观时的过渡持续时间,默认是0.4s
  resize:true, //调整窗口大小时自动调整元素大小和位置,此项不推荐关闭
  initLayout: true,//默认为true,在初始化时候启用布局,如果设置为在初始化时禁用布局,可以在初始布局之前使用方法或添加事件,执行玩自定义方法后,在使用$grid.masonry()方法来初始化
})

//如果我initLayout: false,那么在初始化布局前,会先执行此方法,然后在调用$('.grid').masonry()方法进行初始化,下面方法只是举例
$grid.masonry( 'on', 'layoutComplete', function() {
  console.log('layout is complete');
});
// 如果initLayout: true,则不需要此方法
$grid.masonry();

/** masonry的配置项一共有以下,不再多做介绍,可以自行去看英文官网。
- Recommended 
- itemSelector 
- columnWidth 
- Layout
- Element sizing 
- gutter
- horizontalOrder 
- percentPosition
- stamp 
- fitWidth
- originLeft 
- originTop
- Setup 
- containerStyle 
- transitionDuration 
- stagger 
- resize 
- initLayout
**/

设置完毕后,得到如下图的布局展示,因为我设置了horizontalOrder: true原因,所以图片排版会尽量按照从左到右方式来布局。并且因为我设置的图片宽度为百分比,所以无论是缩小和放大元素,一行都会呈现四张图片。

image.png

另外,我们也可以使用固定像素宽度来设置图片,以防图片变形。我们将图片容器的宽度从25%改为200px

 .grid-item {
   position: relative;
   width: 200px;
   border: 2px solid hsla(0, 0%, 0%, 0.5);
   box-sizing: border-box;
   counter-increment: count;
}

将js代码中的masonry配置项中的 percentPosition: true去除。这时候,我们得到的排版效果如下图,我们可以发现照片宽度被固定在200px,并且尽可能占满一行,无法占满则换行。

image

当我们缩小浏览器的宽度时候,照片会自适应宽度布局。如下图:
image

到这里,我们完美实现了瀑布流布局的展示。不过此插件要注意浏览器的兼容性,我在safari使用变没有生效,而chrome则没有问题。

类似的插件还有isotope等,在这里不再铺开说了,masonry也有着各种各样的布局方式,感兴趣的可以去官网看。

查看原文

赞 2 收藏 2 评论 0

Coding猫 发布了文章 · 9月13日

Centos7内网环境搭建yum源

在很多情况下,我们服务器因为安全问题,必须处在内网环境,这时候就无法自动通过yum命令下载互联网上的软件源,很多人为这个问题头疼,这里我简单介绍下如果在内网环境搭建yum源。关于centos7安装,可以参考我另一篇文章:Centos7的安装全过程

centos官网下载镜像包

image.png

访问centos官网,我这里用的centos7.4版本,因为我之前系统安装的都是7.4版本,我们下载对应的iso镜像包CentOS-7-x86_64-Everything-1708.iso,大约8G大小,下载速度比较慢,一定要提前下载好。

将下载好的CentOS-7-x86_64-Everything-1708.iso镜像文件上传到服务器的/home目录下。

image.png

注意:如果我们是用的虚拟机装的centos7,则一定先要安装VMware Tools,然后开启共享文件夹,才能把镜像文件拷贝至虚拟机的centos系统中去。如果我们没用虚拟机,直接U盘拷贝进去便可。如果是直接安装在服务器上,可以通过软件xftp上传,因为U盘上传过程中,文件大于8G,会出现各种问题。而xftp不受文件大小限制。

创建镜像挂载

[root@localhost ~]# mkdir -p /media/CentOS7        ##/media目录下创建文件夹CentOS7文件夹

挂载镜像文件

# 先进行手动挂载 
[root@localhost ~]# mount -t iso9660 -o loop /home/CentOS-7-x86_64-Everything-1708.iso /media/CentOS7/ 
mount: /dev/loop0 写保护,将以只读方式挂载

image.png

手动挂载完毕后,进行自动挂载。执行以下命令,打开文件。

[root@localhost ~]# vim /etc/fstab

在末尾加入以下语句(路径根据自己挂载实际地址填写),注意空格。

/home/CentOS-7-x86_64-Everything-1708.iso /media/CentOS7 iso9660 defaults,ro,loop 0 0

image.png

之所以要修改此文件,是因为,磁盘被手动挂载之后都必须把挂载信息写入/etc/fstab这个文件中,否则下次开机启动时仍然需要重新挂载。系统开机时会主动读取/etc/fstab这个文件中的内容,根据文件里面的配置挂载磁盘。这样我们只需要将磁盘的挂载信息写入这个文件中我们就不需要每次开机启动之后手动进行挂载了。

命令执行完毕后,查看挂载情况。

[root@localhost ~]# df -h  
                          容量  已用  可用   已用%  挂载点 
/dev/mapper/centos-root   70G  3.9G   67G    6%  / 
devtmpfs                 473M     0  473M    0%  /dev 
tmpfs                    489M     0  489M    0%  /dev/shm 
tmpfs                    489M  7.2M  481M    2%  /run 
tmpfs                    489M     0  489M    0%  /sys/fs/cgroup 
/dev/sda1               1014M  161M  854M   16%  /boot 
/dev/mapper/centos-home   77G  8.4G   69G   11%  /home 
/dev/loop0               8.1G  8.1G     0  100%  /media/CentOS7 
vmhgfs-fuse              932G  131G  802G   14%  /mnt/hgfs 
tmpfs                     98M  4.0K   98M    1%  /run/user/42 
tmpfs                     98M   24K   98M    1%  /run/user/0

发现/dev/loop0逻辑目录挂载成功,挂载点为/media/CentOS7

新增文件/etc/yum.repos.d/centos7-media.repo

如果是修改原有CentOS-Media.repo文件进行修改本地源,执行安装命令时候则比较麻烦。所以我们通过新作repo源文件来创建yum源指向本地,而不是去修改原有的CentOS-Media.repo源文件。执行命令创建文件。

[root@localhost ~]# vim /etc/yum.repos.d/centos-media.repo    ###创建文件

在文件中输入以下内容。

[centos7-media]  
name=centos7  
baseurl=file:///media/CentOS7  
enabled=1  
gpgcheck=0  
gpgkey=file:///media/CentOS7/RPM-GPG-KEY-CentOS-7   
### [centos7-media]这里是源的名称,保持和文件名称一致 
### name=centos7 这是yum源备注,随便起无所谓。 
### enabled 是否启用本配置,1代表使用,0代表不实用,这里肯定用1。/etc/yum.repos.d文件下,使用中的配置只会有一个。其他文件的此属性必须为0,不然会冲突。 
### gpgcheck=1 #是否检测yum源的签名,防止软件安装的软件被篡改(0:不验证,1:验证,默认为1) ### gpgkey:yum签名秘钥的地址,如果gpgcheck=1,这里必须要填,文件名格式为RPM-GPG-KEY-系统版本,我们可以去挂载地址下,可以找到此文件。

插入后,保存退出。

备份CentOS-Base.repo文件。

[root@localhost ~]# cd /etc/yum.repos.d/ 
[root@localhost ~]# mv CentOS-Base.repo CentOS-Base.repo.bak  
### 这里CentOS-Base.repo文件主要是去网络上找相应的包,我们修改了名称让其失效,就会默认从本地源(enabled=1)的文件读取
执行命令建立缓存 
[root@localhost ~]# yum makecache 
已加载插件:fastestmirror, langpacks 
centos7-media                            | 3.6 kB     00:00 (1/4): centos7-media/group_gz                           | 156 kB   00:00 (2/4): centos7-media/primary_db                         | 5.7 MB   00:00 (3/4): centos7-media/filelists_db                       | 6.7 MB   00:00 (4/4): 
centos7-media/other_db                   | 2.5 MB   
00:00 Determining fastest mirrors 
元数据缓存已建立

到此为止,本地源搭建成功。我们可以尝试安装命令查看是否安装成功

[root@localhost ~]# yum -y install gcc
查看原文

赞 0 收藏 0 评论 0

Coding猫 发布了文章 · 9月13日

Centos7的安装全过程

在安装前,先准备一个至少8G的U盘。我们后面使用U盘安装。

下载Centos 安装包

访问:Centos官网
image.png
点击上图中CentOS Linux

点击跳转网页后,如下图,因为上市时间不长,资料较少,我暂时不安装centos8系统,而是我们选择下载centos7版本的64位系统下载。
image.png
点击x86_64版本后,进入镜像下载页面,随便选取一个开始下载ios文件吧。~~~~
image.png
比如我选择了第一个镜像地址下载。点击进入后如下图:
image.png
一般如果要按照的服务器不是处在内网环境下,不需要修改yum源的话,则选择上面的4.5G的下载即可。下载过程不再描述。
关于内网环境怎么使用自己的yum源,可以参考我这篇文章:Centos7内网环境搭建yum源

下载U盘安装工具

这里我使用的U盘安装工具是:USBWriter,这里提供了下载地址,大家也能自己网上自行下载其他软件。

制作U盘启动盘

当centos的ios文件和U盘工具下载安装后,我们开始制作U盘安装盘。直接打开软件USBWriter,按下图操作即可。
image.png

安装centos7

更改电脑的BIOS启动顺序,这里不再描述,每个品牌电脑修改方式大同小异,另外有些服务器安装前,因为带硬raid卡,需要先进行raid操作,我一般选择raid5或者raid10,尤其是raid10,速度快安全性高。

插入U盘,进入安装界面。

image.png
出现上图操作界面,这时候键盘选择第一项Install CentOS 7,切记别选错了,避免浪费时间。

接下去系统会进入安装操作界面,我下面直接上图说明。
首先进入语言界面,我们直接选简体中文即可。

image.png

软件选择默认情况都是最小安装,可以不更改,如果你想要桌面操作,则进入选项选择GNOME桌面,GNOME桌面的子选项不做勾选。
image.png

安装位置:点击进入如下图所示
image.png
根据实际情况选择要安装的目的地磁盘,勾选要安装的硬盘,然后选择我要配置分区,再点击左上角的完成。

点击完成后,会进入分区操作界面,这里我的分区方案修改为LVM,而不是标准分区,然后点击“点这里自动创建他们”。如果你的硬盘先去安装过系统,则必须先点击-号,删除格式化原先系统。
image.png

根据需求调整分区大小,一般swap是内存的2倍,最大别超过16G。/boot是用于一些配置启动文件,一般500MB-1G就足够。/home用于存放数据,配置完后点击完成。一般情况下,/目录的硬盘容量会默认分配为50G,这里建议缩小一部分/home硬盘容量,添加到/容量中,因为后期安装oracle等,随着服务器运行时间变成,会发现很多/分区中会被占用很多文件,虽然我们可以通过定期清理尽量缩小/容量,但是50G空间还是有点捉襟见肘。所有都修改好后点击下一步。系统会进入准备安装界面。
image.png

以上所有操作都完成后,我们进入配置安装界面,如下图:
image.png
此界面可以设置root密码和创建低权限用户密码。填好后接下来就是等待安装,直至完成,会出现重启按钮。点击重启。
image.png

重启后进入欢迎界面(记得U盘拔掉,否则还是U盘优选加载),同意许可信息后就进入正式页面,可以使用了。
image.png
image.png

查看原文

赞 1 收藏 1 评论 0

Coding猫 发布了文章 · 9月12日

css中filter属性和backdrop-filter的应用与区别

filter和backdrop-filter具有一定区别:

  • Filter不仅仅作用于当前元素,后代元素也会继承这个属性,作用于一个空背景元素则没有效果。
  • backdrop-filter 是使透过该层的底部元素模糊化
  • backdrop-filter属性可以让你为一个元素后面区域添加图形效果(如模糊或颜色偏移)。 因为它适用于元素背后的所有元素,为了看到效果,必须使元素或其背景至少部分透明。
  • backdrop-filter目前兼容性不佳,尤其是安卓移动端。

filter属性

我们先来说说filter属性,css3中的filter属性简单易用且强大,这些效果作用在图片上可以实现一些特有的特效。而且目前主流浏览器都已经支持了这个属性。

image.png

从上图来看,大部分浏览器的兼容性都是不错的。

我们还是直接用代码来看。

body {
  display: flex;
  width: 100%;
  height: 100vh;
  align-items: center;
  justify-content: center;
}

.img {
  width: 500px;
  height: 500px;
}
<body>
    <img data-original="./img/kyoto.jpg" class="img filter">
</body>

我们定义一张照片在网页中央,先不做任何处理。

image.png

这是原图呈现的效果。

接下来我们看filter的几个比较重要的属性。

opacity

opacity 代表透明度,值为0-1之间的小数,值越大透明度越低。

.filter{
  filter: opacity(.3);
}

如下图展示:

image.png

blur

blur可以设置图片使用高斯模糊效果,单位值是px。所谓高斯模糊,就是指一个图像与二维高斯分布的概率密度函数做卷积。

简单点说:高斯模糊常常用来模拟人眼中的物体变远、变快的效果。在照片处理中,我们常常将背景施以高斯模糊,使得背景仿佛变远了,从而突出前景的人物或物体。一些所谓“先拍照,后对焦”的技术利用的也是高斯模糊这个效果。若想弄出视点飞快移动的效果,也可以对背景使用高斯模糊。

.filter {
  filter: blur(2px);
}

image.png

invert

invert 可以设定反色, 值为0-1之间的小数。

.filter {
  filter: invert(1);
}

image.png

saturate

saturate可以设定照片饱和度,取值范围为数字即可,默认值1,即100%。

.filter {
  filter: saturate(5);
}

比如这里我设置饱和度是500%,如下图效果:

image.png

grayscale

grayscale代表灰度,取值在0-1之间,。

.filter {
  filter: grayscale(1);
}

下图是grayscale为1,即灰度是100%时候的效果。

image.png

另外,如果使用该效果参数里没值的话,也会默认以1,即100%为值取值,即如下面设置。

.filter {
  filter: grayscale();
}

sepia

sepia代表的是照片褐色,类似于大部分美图软件里的怀旧功能的那种效果,取值也是0-1,和grayscale一样。

.filter {
  filter: sepia(1);
}

hue-rotate

hue-rotate用来改变图片的色相,默认值为0deg,取值是角度(angle)。

.filter {
  filter: hue-rotate(90deg);
}

image.png

hue-rotate一般配合css动画使用,可以呈现不一样效果。比如电池充电的动画,随着高度在纵坐标上移,hue-rotate的值逐渐改变,这里因为无法上传git图片,只能看下静态图片:
image.png

image.png

brightness

brightness可以改变图片的亮度,默认值为100%,即1。

 .filter {
   filter: brightness(2);
}

image.png

contrast

contrast代表对比度,这个属性取值和饱和度saturate类似,取值也是数字。

.filter {
  filter: contrast(2.5);
}

这里我们演示对比度是250%时候的效果,如下图:

image.png

drop-shadow

drop-shadow这个属性类似于box-shadow,给图片加阴影。

.filter {
  filter: drop-shadow(20px 20px 10px 20px #000) /**水平阴影位置,垂直阴影位置,模糊距离,阴影颜色**/
}

image.png

backdrop-filter属性

我们回过头来在看backdrop-filter属性以下几点特点

  • backdrop-filter 是使透过该层的底部元素模糊化
  • backdrop-filter属性可以让你为一个元素后面区域添加图形效果(如模糊或颜色偏移)。 因为它适用于元素背后的所有元素,为了看到效果,必须使元素或其背景至少部分透明。
  • backdrop-filter目前兼容性不佳,尤其是安卓移动端。

上面这些只看文字不好理解,我直接上代码:

<div class="container">
  <div class="content"></div>
  <div class="filter">
    Lorem ipsum dolor sit amet consectetur, adipisicing elit. Possimus voluptatem velit quod placeat?
    Cupiditate,
    corporis, et tempore laudantium consequatur labore distinctio nisi inventore totam vero cum est saepe quos
    ad
  </div>
</div>

我们定义了一个container元素div,子元素有content和filter两个div元素。

body {
  margin: 0;
  padding: 0;
}

.container {
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: aqua;
}

.content {
  position: absolute;
  bottom: 40%;
  width: 300px;
  height: 300px;
  background-color: blueviolet;
}

.filter {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50%;
  font-size: 32px;
  z-index: 20;
}

以上元素,我们可以得到如下布局:

image.png

这时候,我们将filter元素改为

.filter {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50%;
  filter: blur(5px);
  z-index: 20;
  font-size: 32px;
}

从代码看,我们添加了filter: blur(5px)。如下图展示效果,我们发现filter元素div和其中的文字内容,都被模糊化了。

image.png

但如果如下修改样式

.filter {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50%;
  backdrop-filter: blur(5px);
  z-index: 20;
  font-size: 32px;

}

使用backdrop-filter: blur(5px)元素,则得到如下图排版

image.png

我们发现,只有filter元素DIV被模糊化,而子内容文字并没有受到任何影响。

.filter {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50%;
  background-color: chocolate;
  backdrop-filter: blur(5px);
  z-index: 20;
  font-size: 32px;

}

但是,如果按照以上代码,给filter元素设置了背景色background-color: chocolate,这时候,就几乎看不到模糊化的效果。

image.png

或者,我们把content元素DIV背景色去除,

.content {
  position: absolute;
  bottom: 40%;
  width: 300px;
  height: 300px;
}

image.png

这就是为什么说,为了看到效果,必须使元素或其背景至少部分透明。

我们发现,backdrop-filter属性还只能在部分最新版浏览器上有效果,所以目前来看,此属性的兼容性较差。

image.png

查看原文

赞 0 收藏 0 评论 0

Coding猫 发布了文章 · 9月12日

Flex布局

上一期我整理介绍了grid布局方式,如果想看的同学,可以直接点击此文章:
Grid布局

这期我把flex布局方式笔记也整理出来了,内容是我自己在根据别人视频学习过程中整理的资料。

目前很多css的框架都使用Flexbox作为基础。浏览器大部分也都兼容。

接下来直接看代码演示,我们先准备一个素材,准备5个div元素,定义为 ABCDE。因为div默认情况下display是block块级元素,所以默认情况下会独占一行。所以我们得到如下图的排版。这就是我们准备的素材。

<div class="box A">A</div>
<div class="box B">B</div>
<div class="box C">C</div>
<div class="box D">D</div>
<div class="box E">E</div>
html {
    font-size: 12px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}

.A {
    background-color: #6dd98f;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

Flex Container和Flex Items

Flex布局方式主要就分为2个角色,Flex Container和Flex Items,也就是父容器和子项目。我们先来改写素材。

<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

将四个div元素外部包括一个flex-container父容器,并且设置flex-container的display为flex。那么我们便得到了如下图的布局。

.flex-container {
    display: flex;
      background-color: #2B34F5;
}

image.png

这里父容器就是flex-container元素,而里面五个div则便是flex items子项目。

flex container中属性

flex-direction

flex-direction这个属性是定义父容器中子项目,即flex items的排序方向。

flex-direction的默认值一般为 row,即是横向排序。

如果你改成:

flex-direction: column;

这时候便是纵向排序。

image.png

另外还有以下排序方式:

flex-direction: row-reverse;  //横向倒转排序。

如下图:

image.png

flex-direction: column-reverse; //纵向倒转排序。

如下图:

image.png

这里有一个比较重要的知识点:主轴(main-axis)和交叉轴(cross-axis)。当flex属性不同时候,主轴和交叉轴不同。这个知识点需要和justify-content和align-items结合起来使用,下面我们先来介绍justify-content和align-items这2个知识点。

flex-direction属性主轴(main-axis)交叉轴(cross-axis)
rowrowcolumn
columncolumnrow

justify-content和align-items

justify-content是设置主轴的排序方向的。而align-items则是设置交叉轴的排序方向的。

我们还是看代码:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: center;
}

我们把flex-direction设置为row横向排序,这时候设置justify-content,即主轴方向居中,此时的主轴便是row,那么我们可以得到如下图的效果:

image.png

但是当我们把代码改为flex-direction: column时候,此时主轴便成了colunm,设置justify-content: center属性则不会得到水平方向的居中,如下图。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: column;
    justify-content: center;
}

image.png

此时,如果我们要得到水平方向居中,则应该设置align-items:center,而不是justify-content: center。因为此时row水平方向是属于交叉轴。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 500px;
}

那我们便把flex-container父容器高度设置大点,这时候主轴便是column,那么justify-content: center熟悉会让子元素垂直居中于父容器内,则align-items: center则会让子元素水平居中于父容器内。

image.png

从这个举例来看,是不是很好理解主轴和交叉轴概念。

另外,justify-content除了center外,还有其他各种属性

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
      height: 500px;
      align-items: center;
}

我们把父容器恢复为flex-direction: row水平布局。

justify-content: flex-start; //沿着主轴起始方向排版布局

如下图:

image.png

justify-content: flex-end;//沿着主轴结束方向排版布局

如下图:

image.png

这里要记住一点:

设置flex-direction: row属性时候,justify-content属性设置为flex-start或flex-end,子元素都是由左至右排序。设置flex-direction: colunm属性时候,justify-content属性设置为flex-start或flex-end,子元素都是由上至下排序。即顺序都是ABCDE,不会是EDCBA。

flex-wrap

flex-wrap即是会不会分行的意思。

<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

我们在父容器中加入多个子div,这时候我们缩小浏览器的宽度。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
}

image.png

这时候会发现,子div还是会被压缩在水平方向一行,每个子div宽度会被挤压。这是因为flex-wrap默认的属性值是nowrap,即不换行的意思,所以不管怎么添加子div,都只会在同一行。

如果我们修改属性flex-wrap: wrap:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
    flex-wrap: wrap;
}

image.png

这时候,超出宽度的子div便会被移到下一行中。这时候我们再配合justify-content和align-items两个属性,就能得到不一样效果,比如下面排版:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    height: 500px;
    flex-wrap: wrap;
}

image.png

flex-flow

flex-flow是flex-direction和flex-wrap的组合起来的缩写。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap; 
    justify-content: center;
    align-items: center;
    height: 500px;
}

flex-flow: row wrap; 在这里便是flex-direction:row,flex-wrap:wrap的缩写。这个可以根据个人习惯用此属性或者分2个属性编写。

align-content

align-content这个属性,是当flex-wrap设定为wrap的时候,即是有二行以及二行以上时候才会生效。直接看下图:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 500px;
}

不设置align-content时候的如下图:

image.png

align-content: center;

align-content: center时候如下图:

image.png

align-content: space-between;

align-content: space-between时候如下图:

image.png

align-content: flex-start;

align-content: flex-start时候如下图:

image.png

由上面举例可知道,align-content是设定二行以二行以上时候,行与行之间的对齐方式。

Flex Items中属性

order

order属性用于调整flex item的排序位置。我们看以下参考案例:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}
<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

我们还是先设定父容器下5个子div,以flex布局方式,自动换行。

.B {
    background-color: #0c7899;
    order: 1;
}

这时候我们在B子DIV中加入属性值order:1,那么我们会得到如下布局排版方式。

image.png

发现div B已经到了末尾,这是因为flex item的order默认值都是0,当B设定为1时候,因为flex布局容器会根据order数字以小到大排序,B便会移动至末尾排序。

.B {
    background-color: #0c7899;
    order: -1;
}

如果我们把B DIV的order设置为-1,则会排序到第一个。

image.png

order可以随意将个别flex item的位置进行改变。

align-self

align-self是用于覆盖flex container(父容器)的align-item的设置的

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;

}

比如父容器中,我们align-items的值设置了center居中。

.A {
    background-color: #6dd98f;
    align-self: flex-end;
}

如以上代码,我们修改DIV A的align-self属性为flex-end。那么我们会得到如下图排版:

image.png

flex-basis

flex-basis是设置flex-item的主轴方向的大小的。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}

比如父容器中,我们设置主轴为row,并可以换行。

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 200px;
}

在父容器的子div中添加flex-basis: 200px属性,此时此属性即代表子div的宽度为200px;如下图:

image.png

而如果我们将主轴改为column。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: column wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}

此时flex-basis代表的是子div的高度,如下图:

image.png

要记住一点,在设置flex-basis后,原有的高度或者宽度都会失效,都会改为flex-basis的设定值去计算宽度或高度。如果flex-basis设置为0,如果没有overflow的设定,此时容器宽度或高度则取决于子div容器内内容的大小。如下图:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}
.box {
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 0;
}

image.png

如果子容器再添加overflow属性,则如下面情况:

.box {
    overflow: hidden;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 0;
}

image.png

overflow: hidden情况下,不会显示子div。

flex-grow

flex-grow是指当flex container的主轴方向有剩余空间的时候,flex item(容器子元素)沿主轴方向扩大的设置。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: flex-start;
    align-items: center;
    height: 200px;
    width: 500px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}
<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

image.png

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-grow: 1;
}

box属性中,我们加入了 flex-grow: 1,这时候原先的排版便会变成以下结果:

image.png

子容器直接平均撑满整个父容器。这是因为五个div属性都是flex-grow: 1,那五个div便都是独占一份,会各自占剩余空间200px中的一份,即40px。

如果我们不给每个子div设定flex-grow,只设定其中A DIV元素


.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}
.A {
    background-color: #6dd98f;
    flex-grow: 1;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

那么从上图排版,我们会发现A DIV会独占剩余200px的所有空间。也就是A DIV宽度变成了60+200=260px;

而当主轴改为column时候,则是垂直方向A独占剩余空间。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: column wrap;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
    width: 500px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;

}

.A {
    background-color: #6dd98f;
    flex-grow: 1;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

flex-shrink

flex-shrink则与flex-grow相反。是指当flex item子容器主轴方向的大小总和,超出父容器flex container的时候,flex item沿主轴方向如何缩小的设定。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;
    height: 300px;
    width: 240px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}

我们将父容器宽度改为240px,主轴为row方向,不换行。每个div设定为60px,那么理论上5个div应该有300px总和。但是现在父容器只有240px,少了60px。

image.png

我们发现五个div还在同一行,但是宽度被缩减了。这是因为flex-shrink默认值都是1。

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-shrink: 0;
}

我们现在每个div设置flex-shrink: 0。这时候代表当主轴方向空间不足时候,不会去压缩子容器的宽度。那么我们可以得到下图排版:

image.png

.A {
    background-color: #6dd98f;
    flex-shrink: 1;
}

.B {
    background-color: #0c7899;
    flex-shrink: 1;
}

.C {
    background-color: #961375;
    flex-shrink: 1;
}

.D {
    background-color: #bb7e38;
    flex-shrink: 1;
}

.E {
    background-color: #cfec9f;
}

我们在子DIV A、B、C、D中都加入属性值flex-shrink: 1,这代表ABCD四个DIV都各自分担一份被缩小的空间,也就是60/4=15px,那么ABCD四个div都会缩小为60-15=45px的宽度,而E因为flex-shrink:0,所以仍然会是60px的宽度。如下图排版:
image.png

flex

flex的属性是flex-grow,flex-shrink和flex-basis组合起来的缩写。类似于父容器属性flex-flow,根据每个人写法习惯不同,可以拆分成三个属性分别写,也可以组合编写。这里不多做介绍。

前端学习过程要感谢B站的CodingStartup的Steven,不过他的讲解基本是粤语和视频,很多笔记我只能在看的过程自己整理,虽然直接我也从事程序开发,但是很多时候只知道要这么做,却不知道为什么要这么做,所以工作几年后重新回头巩固知识,以上是我在学习过程中自己整理的学习笔记,希望可以帮到大家。

查看原文

赞 0 收藏 0 评论 0

Coding猫 发布了文章 · 9月10日

css定位的五种方式

position

根据学习他人的资料,自己整理下笔记,巩固下css中五种定位方式知识点,温故知新,不断在工作中提升自我。

position 属性的五个值:

  • static
  • relative
  • fixed
  • absolute
  • sticky(粘性定位)

下面直接上图和代码举例:

static

html里面所有元素的position的默认值都是static,static会跟随html排版的流程移动。static对于top,left,right,bottom设定值不会生效。

比如我在static的div上面放了一个高度120px的div,则static属性div会被挤下去。

<div class="height"></div>
<div class="static"></div>
.static{
  position:static;
  width:360px;
  height:360px;
}
.height{
  width:750px;
  height:120px;
}

image.png

absolute

绝对定位,元素会它最近的一个父类容器去定位,该父类容器position的值必须是:relative、absolute、fixed,若没有这样的父元素,则该元素会相对于body进行定位。

绝对定位偏移值由其top、bottom、left、right值确定。

而绝对定位的元素若超出其父元素的边界,要想将溢出的部分隐藏,则想隐藏在哪个父类里,该父类必须同时设置position为relative/absolute/fixed中一种,并且overflow需要设定为hidden。

看以下例子:

<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="absolute"></div>
.height{
  width:750px;
  height:120px;
}
.absolute{
  position:absolute;
  width:240px;
  height:240px;
  right:80px;
  bottom:60px
}

image.png

从上图看,absolute定位并不会受到到height元素排版影响。

我们在多复制几份height元素,让页面出现滚动轴,这时候会发现absolute元素会随滚动轴滚动。

image.png

另外,如下图,如果我们把absolute元素嵌套入absolute元素中,则最里层的div会根据父层的absolute元素的位置去定位。正好印证了上面说的元素会它最近的一个父类容器去定位,该父类容器position的值必须是:relative、absolute、fixed,若没有这样的父元素,则该元素会相对于body进行定位。

<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="absolute">
  <div class="absolute"></div>
</div>

image.png

relative

relative和static很相似,都会跟随html排版流程移动,但它比static多了top,left,right,bottom的设定。即它是跟随html排版流程定位之外,还会透过top,left,right,bottom去调整位置。以下举例:

<div class="height"></div>
<div class="relative"></div>
.height{
  width:750px;
  height:120px;
}
.relative{
  position:relative;
  width:360px;
  height:360px;
  top:60px;
  left:150px;
}

image.png

从上图一目了然,relative元素跟随了height的排版而浮动了,并且根据top和left来进行定位。

增加了一个div,relative元素向下移动。

<div class="height"></div>
<div class="height"></div>
<div class="relative"></div>

image.png

relative最重要一个功能就是在他里面的子元素,如果定位方式是absolute,则子元素会根据relative的位置去定位。

<div class="height"></div>
<div class="height"></div>
<div class="relative">
  <div class="absolute"></div>
</div>
.height{
  width:750px;
  height:120px;
}
.relative{
  position:relative;
  width:360px;
  height:360px;
  top:60px;
  left:150px;
}
.absolute{
  position:absolute;
  width:240px;
  height:240px;
  right:80px;
  bottom:60px;
}

image.png

从这张图看,我们会发现absolute子元素的right和bottom是根据relative元素的位置去定位的。这在平时项目中非常常用。

而如果你将relative元素替换为static,则会发现absolute元素完全无视static元素。

<div class="height"></div>
<div class="height"></div>
<div class="static">
  <div class="absolute"></div>
</div>

.height{
  width:750px;
  height:120px;
}
.static{
  position:static;
  width:360px;
  height:360px;
}
.absolute{
  position:absolute;
  width:240px;
  height:240px;
  right:80px;
  bottom:60px;
}

image.png

fixed

fixed和absolute很相似,不同地方有两点:

  • fixed会定位到屏幕中的固定位置,所以即使滚动页面,fixed也会一直保持在那个位置。
  • 如果fixed元素设定了top,left,right,bottom属性,那么它即使放在relative里面,fixed也会根据页面,即body去定位,而不会根据relative元素去定位。
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="fixed"></div>
.height{
  width:750px;
  height:120px;
}
.fixed{
  position:fixed;
  width:240px;
  height:240px;
  left:80px;
  bottom:60px;
}

image.png

先看下图,我们把fixed元素嵌套入relative元素中,并没设定top,left,right,bottom属性,这时候fixed元素会根据父元素relative排版

<div class="height"></div>
<div class="relative">
  <div style="background-color:red;width:50px;height:50px;position:fixed" ></div>
</div>
.height{
  width:750px;
  height:120px;
}
.relative{
  position:relative;
  width:360px;
  height:360px;
  top:60px;
  left:150px;
}

image.png

而一旦fixed元素设定了top,left,right,bottom属性,那么它即使放在relative里面,fixed也会根据页面,即body去定位,而不会根据relative元素去定位

<div class="height"></div>
<div class="relative">
  <div style="background-color:red;width:50px;height:50px;position:fixed;top:50px;left:10px;" ></div>
</div>

image.png

sticky(粘性定位)

sticky 是css定位新增的一个属性;可以说是相对定位relative和固定定位fixed的结合;

它主要用在对scroll事件的监听上,简单说在滑动过程中,某个元素的距离其父元素的距离达到 sticky 粘性定位 要求时;

position:sticky 这时的效果就相对于 fixed 定位,固定到适当的位置。

如图,我们多添加height元素,并直至出现滚动轴。

<div class="height"></div>
<div class="height"></div>
<div class="sticky"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
<div class="height"></div>
.height{
  width:750px;
  height:120px;
}
.sticky{
  position:sticky;
  width:240px;
  height:90px;
  top:0;
}

image.png

当我们滑动滚动轴页面上移后,当sticky元素触到页面顶部时候,就会固定在顶部。固定到顶部原因是我们将他的top设定为 0。所以当top与上方相距离0px时就会触发。如下图:

image.png

image.png

sticky粘性定位可以较少代码实现弹性固定场景,比如导航栏。但是兼容性来看,因为是css新属性,目前还比较差。我们可以参考以下浏览器兼容性图发现,浏览器也是从2014年开始慢慢支持的

image.png

image.png

关于css中定位的五种方式就介绍完毕了。

最后很感谢B站Codingstartup的Steven学习视频。根据他的视频和素材结合我自己理解整理的笔记,用来在工作中不断巩固和提升自己。

查看原文

赞 0 收藏 0 评论 0

Coding猫 发布了文章 · 9月10日

Grid布局

最近在重新巩固html方面的知识,这里分享下自己学习过程中跟随别人学习的笔记和心得。

目前,网页布局一般有table,float,flexbox和grid布局。

table和float布局较为老,目前有淘汰趋势了,而flexbox布局是现在比较流行的布局方式。

flexbox布局属于一维布局,Grid属于二维布局的排版方式。

一个Flexbox容器智能控制一个方向,水平或者垂直方向。如果要控制另一个方向,则要再添加一层flexbox容器。

Grid可以一次控制2个方向,就可以直接定义容器内元素的位置了。

Grid Line

下面用项目直接来看:

我们画出了一个5*5个格子的div容器,id定义为grid-container,其中row和column都标注了起始点至结束点的线条序列。

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:100px 100px 100px 100px 100px;
  grid-template-columns:100px 100px 100px 100px 100px;
}

如以上代码,我们设置将容器设置为grid布局,并且rows和columns分隔成100px等格的方块。效果图如下:
image.png

<div id="grid-container">
  <div class="cell-1"></div>
  <div class="cell-2"></div>
</div>

容器中,我们设定了2个div,分别是cell-1和cell-2。

.cell-1{
  background-color:green;
  grid-row:2/4;
  grid-column:1/3;
}
.cell-2{
  background-color:yellow;
  grid-row:4/6;
  grid-column:3/6;
}

按以上代码,我们设置了2个子div的背景色和row与column占得位置。得出的图形如下:

image.png

grid-row:num/numgrid-column:num/num意思是row或者column方向由第几条线到第几条线的值,这些线在grid布局里我们称为==grid line==。

除了这种写法,我们还有另外几种写法:

第二种写法:
.cell-1{
  background-color:green;
  grid-area:2/1/4/3;
}
.cell-2{
  background-color:yellow;
  grid-area:4/3/6/6;
}

grid-area:grid-area定义的顺序是gird-row的第一个grid line值,grid-column的第一个grid line值, gird-row的末尾grid line值,grid-column的末尾grid line值。

第三种写法:
.cell-1{
  background-color:green;
  grid-row:2/span 2;
  grid-column:1/span 2;
}
.cell-2{
  background-color:yellow;
  grid-row:4/span 2;
  grid-column:3/span 3;
}

grid-row:num/span num和grid-column:num/span num意思是从第几个grid line延伸几格的意思。

一般第三种方法较为常用。

最后种方法

因为我们实际项目中,不可能看到grid line的具体数字的,最后种方法,我们需要定义grid line的坐标值,直接根据坐标值来定位。

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:[Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
  grid-template-columns:[X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
}

我们直接在父容器中,设定grid line的坐标值。rows方向设定为Y轴,columns设定为X轴。

image.png

那我们可以直接从css代码就一目了然知道grid line的坐标轴了。

.cell-1{
  background-color:green;
  grid-row:Y1/Y4;
  grid-column:X1/X3;
}
.cell-2{
  background-color:yellow;
  grid-row:Y4/Y6;
  grid-column:X3/X6;
}

那原来写法便可以改为此种写法。一目了然。

image.png

Grid Areas

grid的分隔线我们称作grid line,而grid中的方格我们则成为grid area。

还是直接用代码演示:

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:[Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
  grid-template-columns:[X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
  grid-template-areas:"header header header header header"
                      "nav main main main main"
                      "nav main main main main"
                      "nav main main main main"
                      ". footer footer footer .";
}

我们直接定义grid-template-areas的值,如以上代码。

这里定义的值的意思便是给每个方块设置了别名,而.则代表忽略该方块:

image.png

<div id="grid-container">
  <div class="cell-1"></div>
  <div class="cell-2"></div>
  <div class="cell-3"></div>
  <div class="cell-4"></div>
</div>

我们设置grid-container的div使用grid布局,并且有四个子容器

.cell-1{
  background-color:green;
  grid-area:header;
}
.cell-2{
  background-color:yellow;
  grid-area:footer;
}
.cell-3{
  background-color:red;
  grid-area:nav;   
}
.cell-4{
  background-color:black;
  grid-area:main;
}

这时候我们设定每个子容器所拥有的area别名,就能得到以下的图。

image.png

我们再把用来标尺的背景图去除。就能得到以下结构:

image.png

是否很眼熟,一般的网页布局就出现了。

假如我们想把每个布局设置下间隔,可以在grid-container设置row-gap和column-gap属性,并把背景色宽度高度重新设置。便可以发现如下图的布局结构了。

#grid-container{
  display:grid;
  width:540px;
  height:540px;
  background-color:#eee;
  grid-template-rows:[Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
  grid-template-columns:[X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
  grid-template-areas:"header header header header header"
                      "nav main main main main"
                      "nav main main main main"
                      "nav main main main main"
                      ". footer footer footer .";
  row-gap:10px;
  column-gap:10px;
}

image.png

fr和repeat()

fr这个单位是专门用于Grid的比例的单位,1fr即占一份的意思。

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:1fr 1fr 1fr 1fr 1fr;
  grid-template-columns:1fr 1fr 1fr 1fr 1fr;
  grid-template-areas:"header header header header header"
                      "nav main main main main"
                      "nav main main main main"
                      "nav main main main main"
                      ". footer footer footer .";
  row-gap:10px;
  column-gap:10px;
}

比如这里,设置了5个1fr,那么1fr就表示占1/5的大小。

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:3fr 1fr 1fr 1fr 1fr;
  grid-template-columns:1fr 1fr 1fr 1fr 1fr;
  grid-template-areas:"header header header header header"
                      "nav main main main main"
                      "nav main main main main"
                      "nav main main main main"
                      ". footer footer footer .";
  row-gap:10px;
  column-gap:10px;
}

grid-template-rows改成3fr 1fr 1fr 1fr 1fr;,则代表第一个row占比3/7权重区域。从下图看,top区域变大。

image.png

这里我们重复写fr有点累吧,所以这时候可以用到repeat这个函数。

repeat(time,content):time代表要重复多少次,content则代表要重复些什么。

所以,刚才的代码可以改成这样:

#grid-container{
  display:grid;
  width:500px;
  height:500px;
  background-color:#eee;
  grid-template-rows:3fr repeat(4,1fr);
  grid-template-columns:repeat(5,1fr);
  grid-template-areas:"header header header header header"
                      "nav main main main main"
                      "nav main main main main"
                      "nav main main main main"
                      ". footer footer footer .";
  row-gap:10px;
  column-gap:10px;
}

这样就会很清晰,当分隔数量多的时候,就不会乱了。但要注意一点:

==repeat不适用于grid-template-areas==

以上就是css grid布局的所有内容,前端学习过程要感谢B站的CodingStartup的Steven,不过他的讲解基本是粤语和视频,很多笔记我只能在看的过程自己整理,虽然直接我也从事程序开发,但是很多时候只知道要这么做,却不知道为什么要这么做,所以工作几年后重新回头巩固知识,以上是我在学习过程中自己整理的学习笔记,希望可以帮到大家。

查看原文

赞 0 收藏 0 评论 0

Coding猫 关注了标签 · 2018-08-31

前端

Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征。在互联网的演化进程中,网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为主。2005年以后,互联网进入Web 2.0时代,各种类似桌面软件的Web应用大量涌现,网站的前端由此发生了翻天覆地的变化。网页不再只是承载单一的文字和图片,各种富媒体让网页的内容更加生动,网页上软件化的交互形式为用户提供了更好的使用体验,这些都是基于前端技术实现的。

Web前端优化
  1. 尽量减少HTTP请求 (Make Fewer HTTP Requests)
  2. 减少 DNS 查找 (Reduce DNS Lookups)
  3. 避免重定向 (Avoid Redirects)
  4. 使得 Ajax 可缓存 (Make Ajax Cacheable)
  5. 延迟载入组件 (Post-load Components)
  6. 预载入组件 (Preload Components)
  7. 减少 DOM 元素数量 (Reduce the Number of DOM Elements)
  8. 切分组件到多个域 (Split Components Across Domains)
  9. 最小化 iframe 的数量 (Minimize the Number of iframes)
  10. 杜绝 http 404 错误 (No 404s)

关注 152566

Coding猫 关注了标签 · 2018-08-31

关注 81989

认证与成就

  • 获得 3 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-08-27
个人主页被 143 人浏览