milligram css 源码浅析

news/发布时间2024/5/15 15:00:40

一、前言

milligram 是我在 20 年接触并使用的一个 CSS 库,他的出现时间已经无法溯源了,根据 npm 上的发布时间最早是 2015 年,而在国内名气起来的时间大概就是 2020 年了,同时 milligram 最后的更新也停在了那一年。

由于当时只需要做一些简单的页面,只需要一些简单的布局及美观的样式足可以满足我的需求,所以在 CSS 库的选择上排除了当时 Bootstrap、 Bulma、Foundation 这些相对笨重,且功能复杂的库,也因此喜欢上了这个小巧简洁的 css 库。

时至今日,前端三大框架几乎统治整个前端界,从而带来了各类强大的 UI 组件库,这也导致这类简洁的样式库存在感越来越低了。

二、Milligram 介绍

Milligram 是一个简洁、小巧 CSS 库,它专注于提供一个轻量级的样式库,使得在网页项目中添加样式变得非常简单。Milligram 的设计理念是尽可能少地干预你的设计,只提供了一些基础的样式和组件,使得你可以更容易地构建自己的定制化界面。

Milligram 具有一下几个特点:

  1. 轻量级:Milligram 非常小巧,通过 gzip 压缩后仅有 2KB 大小。
  2. 现代化:Milligram 采用了现代化的 CSS特性 和响应式设计,适用于各类设备显示。
  3. 基本样式:Milligram 直接对常见的HTML元素(如表格、按钮)提供了基本样式,从而使用时无须记住很多类名,同时也更容易复写样式。
  4. 网格系统:Milligram包含了一个简单的网格系统,可以快速构建响应式的布局。

虽然 Milligram 自称是一个功能简单的CSS框架,但我认为他更偏向于是一个 CSS 库,不过但正是由于其轻量级和现代化的设计,它非常适合那些希望从零开始构建自己定制样式的开发者。我当时选择的原因正是因为足够简单、同时含有网格系统和简约的 UI 设计,如果仅仅做一些简单的网页,我还是推荐使用的。

三、源码浅析

这篇文章不对使用方法进行讲解了,一是需要手动添加的类其实很少,二是官网写的也足够详细了,三则是现在大概对其感兴趣、想要真正使用的人可能并不多,所有我也不必大废笔墨去介绍用法,直接进入正题。

其实 Milligram 并没有特别复杂的设计,实际代码更是没有多少行,否则也不可能压缩后仅仅 2kb, 我们也只是欣赏一下代码。

目录设计

Milligram 的目录很干净,除了根目录的配置文件,只剩下 test 单元测试、.github github 仓库的一些配置、dist 打包输出目录、以及核心的 src 源码目录。

Pasted image 20230723230307.png

通过目录我们便能大概看出/推测出许多东西:

  • 首先 milligram 的整个源码由 sass 编写
  • 其次 milligram.sass 应该就是整个目录的主文件
  • 其他所有 _ 前缀开头的都是组件样式,在 Bootstrap 的源码中,也是使用 _ 的命名方式。

通过文件名称,我们也能很清晰的看出各个文件的作用。

milligram.sass 源码

可以看到 milligram.sass 只做了一件事,就是将所有组件样式文件导入。

@import _Color
@import _Base
@import _Blockquote
@import _Button
@import _Code
@import _Divider
@import _Form
@import _Grid
@import _Link
@import _List
@import _Spacing
@import _Table
@import _Typography
@import _Image
@import _Utility

_Color.sass

color.sass 中,定义了几个全局的主题颜色变量,如果想修改样式的主题色,只需要改动这里就可以了。

$color-initial: #fff !default
$color-primary: #9b4dca !default
$color-secondary: #606c76 !default
$color-tertiary: #f4f5f6 !default
$color-quaternary: #d1d1d1 !default
$color-quinary: #e1e1e1 !default

_Base.sass 源码

base.sass 主要是一些基础的全局设置。

// Set box-sizing globally to handle padding and border widths
*,
*:after,
*:beforebox-sizing: inherit// The base font-size is set at 62.5% for having the convenience
// of sizing rems in a way that is similar to using px: 1.6rem = 16px
htmlbox-sizing: border-boxfont-size: 62.5%// Default body styles
bodycolor: $color-secondaryfont-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-seriffont-size: 1.6em // Currently ems cause chrome bug misinterpreting rems on body elementfont-weight: 300letter-spacing: .01emline-height: 1.6

这里就涉及到一些基础知识:为什么 html 标签要设置为 62.5% ?

根据注释的解释是:基本字体大小设置为62.5%,以便以类似于使用 px 的方式调整 rems 的大小:1.6rem=16px。

px、rem、em

先简单介绍一下这 px, em, 和 rem ,这个三个都是用于设置元素尺寸的CSS单位:

  • px(像素)px 是绝对单位,表示屏幕上的像素点。1个px相当于屏幕上的一个物理像素。当使用px设置元素尺寸时,它的大小将保持固定,不会随着用户调整浏览器的缩放或设备的分辨率而改变。因此,使用px来设置元素尺寸可以确保大小始终保持不变。

例如:font-size: 16px; 将文字大小设置为16像素。

  • emem 是相对单位,它是相对于父元素的字体大小来计算的。如果没有设置父元素的字体大小,那么 em 将相对于浏览器默认的字体大小(通常是16px)来计算。如果父元素的字体大小是12px,那么1em相当于12px,2em相当于24px,依此类推。

例如:font-size: 1.5em; 将文字大小设置为父元素字体大小的1.5倍。

  • remrem 也是相对单位,但它是相对于根元素(通常是HTML元素)的字体大小来计算的。与em不同,rem 的参考点始终是根元素的字体大小,因此它对于构建响应式布局非常有用。

例如:如果根元素的字体大小是16px,font-size: 2rem; 将文字大小设置为32px。

那么为什么要这里要设置为 62.5% 呢?

这是因为浏览器的默认字体一般都是 16px, 那么所有浏览器都符合就是 1em = 16px 换算设定,
根据 1em = 16px 的设定,我们可以得出 12px = 0.75em, 10px = 0.625em。 为了简化 rem、em 的换算,只需要在 html 选择器中声明 font-size: 62.5%,就能使 em 值变为 16px * 62.5% = 10px, 这样 12px=1.2em, 10px=1em

为什么选择 10px ?因为这个值便于计算和转换。当我们使用rem单位时,1rem 等于根元素的字体大小。所以,将HTML的字体大小设置为10px之后,我们只需要将原来的 px 数值除以 10, 然后换成 em 作为单位就行了。

举个🌰子,如果想要一个元素的宽度是30px,只需要使用 3rem30px / 10 = 3rem)来表示。这也就解释了代码注释中,为什么 1.6rem=16px。

这样做的好处是,使得我们在使用rem单位时更加直观,不需要频繁进行计算和换算,提高了代码的可读性和维护性。

_Button.sass

button.sass 文件下的都是 Button 的一些样式。

.button,
button,
input[type='button'],
input[type='reset'],
input[type='submit']background-color: $color-primaryborder: .1rem solid $color-primaryborder-radius: .4remcolor: $color-initialcursor: pointerdisplay: inline-blockfont-size: 1.1remfont-weight: 700height: 3.8remletter-spacing: .1remline-height: 3.8rempadding: 0 3.0remtext-align: centertext-decoration: nonetext-transform: uppercasewhite-space: nowrap&:focus,&:hoverbackground-color: $color-secondaryborder-color: $color-secondarycolor: $color-initialoutline: 0&[disabled]cursor: defaultopacity: .5&:focus,&:hoverbackground-color: $color-primaryborder-color: $color-primary&.button-outlinebackground-color: transparentcolor: $color-primary&:focus,&:hoverbackground-color: transparentborder-color: $color-secondarycolor: $color-secondary&[disabled]&:focus,&:hoverborder-color: inheritcolor: $color-primary&.button-clearbackground-color: transparentborder-color: transparentcolor: $color-primary&:focus,&:hoverbackground-color: transparentborder-color: transparentcolor: $color-secondary&[disabled]&:focus,&:hovercolor: $color-primary

从这段代码可以看的出来,milligram 通过 type 属性将各类表单按钮都获取到了,同时通过 [disabled] 属性设置禁用后的样式。

使用 input[type='color'] 这样 标签 + 属性 的 CSS选择器来修改特定类型的表单元素样式有几个优点:

  1. 精确选择:这些选择器允许你非常精确地选择特定类型的表单元素。通过指定type属性值,你可以选择到你需要修改的具体表单元素,而不影响其他类型的表单元素。
  2. 无需添加额外的类或ID:通过这种方式,无需为每个表单元素添加额外的类名或ID,可以直接通过属性选择器选择到它们。这样可以减少HTML代码的冗余,使代码更简洁。
  3. 代码易读性:这种方式可以使CSS代码更具有可读性,特别是在涉及多个不同类型的表单元素样式修改时。通过选择器的名字,可以清楚地了解你正在针对哪种类型的表单元素进行样式调整。

同时,我们可以看到源码中,对所有类样式都添加了 :hover, :focus 伪类, 进一步提升了用户的交互体验,当我们在实际业务中 需要手写组件时,也应该充分考虑用户的交互体验。

_Form.sass

form.sass 是对各类表单元素的样式设置

input[type='color'],
input[type='date'],
input[type='datetime'],
input[type='datetime-local'],
input[type='email'],
input[type='month'],
input[type='number'],
input[type='password'],
input[type='search'],
input[type='tel'],
input[type='text'],
input[type='url'],
input[type='week'],
input:not([type]),
textarea,
select-webkit-appearance: none // sass-lint:disable-line no-vendor-prefixesbackground-color: transparentborder: .1rem solid $color-quaternaryborder-radius: .4rembox-shadow: nonebox-sizing: inherit // Forced to replace inherit values of the normalize.cssheight: 3.8rempadding: .6rem 1.0rem .7rem // This vertically centers text on FF, ignored by Webkitwidth: 100%&:focusborder-color: $color-primaryoutline: 0selectbackground: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%23' + str-slice(inspect($color-quaternary), 2) + '" d="M0,0l6,8l6-8"/></svg>') center right no-repeatpadding-right: 3.0rem&:focusbackground-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 8" width="30"><path fill="%23' + str-slice(inspect($color-primary), 2) + '" d="M0,0l6,8l6-8"/></svg>')&[multiple]background: noneheight: autotextareamin-height: 6.5remlabel,
legenddisplay: blockfont-size: 1.6remfont-weight: 700margin-bottom: .5remfieldsetborder-width: 0padding: 0input[type='checkbox'],
input[type='radio']display: inline.label-inlinedisplay: inline-blockfont-weight: normalmargin-left: .5rem

通过源码可以清晰的看到,通过 input[type='xxx'] 方式初始化了所有的表单样式,为什么这里不直接对 input 标签进行修改,反而将所有的都写出来? 别忘了 input 标签是有 Button 类型的。

从源码中我们还能学习到一些有趣的用法:

  • input:not([type]) :通过 not([type]) 获取没有显性声明 type 的 input 输入框

  • -webkit-appearance:设置为 none 可以隐藏部件的某些特性,例如 select 元素中显示的指示列表可以展开的箭头。

  • 通过对 select 标签设置 background-image, 显示自定义的下拉箭头

_Grid.sass

grid.sass 是网格布局的核心代码

// .container is main centered wrapper with a max width of 112.0rem (1120px)
.containermargin: 0 automax-width: 112.0rempadding: 0 2.0remposition: relativewidth: 100%// Using flexbox for the grid, inspired by Philip Walton:
// http://philipwalton.github.io/solved-by-flexbox/demos/grids/
// By default each .column within a .row will evenly take up
// available width, and the height of each .column with take
// up the height of the tallest .column in the same .row
.rowdisplay: flexflex-direction: columnpadding: 0width: 100%&.row-no-paddingpadding: 0&> .columnpadding: 0&.row-wrapflex-wrap: wrap// Vertically Align Columns// .row-* vertically aligns every .col in the .row&.row-topalign-items: flex-start&.row-bottomalign-items: flex-end&.row-centeralign-items: center&.row-stretchalign-items: stretch&.row-baselinealign-items: baseline.columndisplay: block// IE 11 required specifying the flex-basis otherwise it breaks mobileflex: 1 1 automargin-left: 0max-width: 100%width: 100%// Column Offsets&.column-offset-10margin-left: 10%//... 省略 10 - 90 之间的代码&.column-offset-90margin-left: 90%// Explicit Column Percent Sizes// By default each grid column will evenly distribute// across the grid. However, you can specify individual// columns to take up a certain size of the available area&.column-10flex: 0 0 10%max-width: 10%//... 省略 10 - 90 之间的代码&.column-90flex: 0 0 90%max-width: 90%// .column-* vertically aligns an individual .column.column-topalign-self: flex-start.column-bottomalign-self: flex-end.column-centeralign-self: center// Larger than mobile screen
@media (min-width: 40.0rem) // Safari desktop has a bug using `rem`, but Safari mobile works.rowflex-direction: rowmargin-left: -1.0remwidth: calc(100% + 2.0rem).columnmargin-bottom: inheritpadding: 0 1.0rem

可以看出来,milligram 是通过 flex 实现网格系统的,根据注释中所言,是参考了 Philip Walton
通过 Flexbox 实现布局有以下优点:

  1. 简单易用:Flexbox 是一种简单、直观的布局模型,相对于传统的浮动布局来说,语法更易理解和使用。它提供了一组直观的CSS属性,使得创建网格布局变得非常简单。
  2. 灵活性:Flexbox 允许容器内的子元素自由伸缩,根据可用空间自动调整其大小和位置。
  3. 自适应能力:Flexbox 布局可以根据容器的大小和内容自动调整,无需指定具体的像素宽度。
  4. 简化嵌套:使用 Flexbox 可以减少网格布局中的嵌套层级,从而简化HTML结构和CSS代码。相较于传统的网格布局方法,使用 Flexbox 可以减少样板代码,提高代码的可读性和可维护性。
  5. 方便的对齐和排序:Flexbox提供了丰富的对齐和排序选项,使得子元素可以轻松地在容器内进行对齐和排序。这在创建复杂布局时非常有用,可以很方便地调整子元素的排列方式。

这里我其实有些疑惑的,我不太明白为什么 column-offsetcolumn 的代码是通过手写的,而不是通过 sass 中的 @each 进行循环,只能当做为了代码更清晰明了吧。

结语

本篇只提取了关键几个源码文件进行讲解,类似于 ImageCodeBlockquote 过于简单的没有再拿出来看的必要了,感兴趣的可以自行查阅

虽然这个库已经停更了,但是可以从源码就能看出来如此简洁的库,即便不再维护也并不影响使用,而且由于代码目录的良好设计,如果需要自行维护扩展也很容易。

milligram 资料

  • Github 仓库地址: https://github.com/milligram/milligram
  • milligram 官网:https://milligram.io/
  • npm 仓库地址:https://www.npmjs.com/package/milligram?activeTab=versions

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/hRrW/771.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

kafka的安装,用于数据库同步数据

1.0 背景调研 因业务需求&#xff0c;需要查询其他部门的数据库数据&#xff0c;不方便直连数据库&#xff0c;所以要定时将他们的数据同步到我们的环境中&#xff0c;技术选型选中了kafkaCDC Kafka是Apache旗下的一款分布式流媒体平台&#xff0c;Kafka是一种高吞吐量、持久…

K8s进阶之路-Pod的生命周期

Pod创建过程&#xff1a; 首先创建一个pod&#xff0c;然后创建一个API Server 和 Etcd【把创建出来的信息存储在etcd中】 然后创建 Scheduler&#xff0c;监控API Server是否有新的Pod&#xff0c;如果有的话&#xff0c;会通过调度算法&#xff0c;把pod调度某个node上 在nod…

如何在CSS中实现背景图片的渐变?

--引言 在CSS中&#xff0c;实现背景图片的渐变通常需要使用linear-gradient或者radial-gradient函数&#xff0c;这些函数可以与背景图像一起使用来创建渐变效果。然而&#xff0c;CSS的渐变并不直接支持使用图像作为渐变的颜色停止点。但你可以通过一些技巧来实现类似的效果…

压缩感知——革新数据采集的科学魔法

引言&#xff1a; 在数字时代&#xff0c;数据以及数据的收集和处理无处不在。压缩感知(Compressed Sensing, CS)是一种新兴的数学框架&#xff0c;它挑战了我们传统上对数据采集和压缩的看法&#xff0c;给医学图像、天文观测、环境监测等领域带来了颠覆性的影响。但到底什么…

【Linux | C++ 】基于环形队列的多生产者多消费者模型(Linux系统下C++ 代码模拟实现)

阅读导航 引言一、生产者消费者模型二、环形队列简介三、基于环形队列的生产者消费者模型&#xff08;C 代码模拟实现&#xff09;⭕Makefile文件⭕ . h 头文件✅sem.hpp✅ringQueue.hpp ⭕ . cpp 文件✅testMain.cpp 温馨提示 引言 在上一篇文章中&#xff0c;我们深入探讨了…

配置oracle连接管理器(cman)

Oracle Connection Manager是一个软件组件&#xff0c;可以在oracle客户端上指定安装这个组件&#xff0c;Oracle连接管理器代理发送给数据库服务器的请求&#xff0c;在连接管理器中&#xff0c;我们可以通过配置各种规则来控制会话访问。 简而言之&#xff0c;不同于专用连接…

SSD201智能高清显示解决方案

一、方案描述 SSD201是高度集成的智能高清显示解决方案,主芯片为ARM Cortex A7,dule core,1.2GHz;SSD201内置DDR2,512Mb;支持H.264/H.265解码; 支持2D图形引擎; 支持MIPI和TTL接口显示屏&#xff0c;分辨率可高达1920x108060fps;支持SPI-Nor/Nand Flash;支持两路Ethernet port…

STM32—DHT11温湿度传感器

文章目录 一.温湿度原理1.1 时序图 二.代码 一.温湿度原理 1.1 时序图 (1).下图一是DHT11总的时序图。 (2).图二对应图一的左边黑色部分&#xff0c;图三对应图一的绿色部分&#xff0c;图四的左部分图对应图一的红色部分&#xff0c;图四的右部分对应图一的黄色部分。 (3)…

平时积累的FPGA知识点(6)

平时在FPGA群聊等积累的FPGA知识点&#xff0c;第六期&#xff1a; 1 万兆网接口&#xff0c;发三十万包&#xff0c;会出现掉几包的情况&#xff0c;为什么&#xff1f; 原因&#xff1a;没做时钟约束&#xff0c;万兆网接口的实现&#xff0c;本质上都是高速serdes&#xf…

Git基本操作(超详细)

文章目录 创建Git本地仓库配置Git配置命令查看是否配置成功重置配置 工作区、暂存区、版本库添加文件--场景一概述实例操作 查看.git文件添加文件--场景二修改文件版本回退撤销修改情况⼀&#xff1a;对于工作区的代码&#xff0c;还没有 add情况⼆&#xff1a;已经 add &#…

K8s服务发现组件之CoreDNS/NodeLocalDNS /kubeDNS

1 coredns 1.1 概述 1.1.1 什么是CoreDNS CoreDNS 是一个灵活可扩展的 DNS 服务器&#xff0c;可以作为 Kubernetes 集群 DNS&#xff0c;在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样&#xff0c;CoreDNS 项目由 CNCF 托管。 coredns在K8S中的用途,…

苍穹外卖学习-----2024/02/19

1.开发环境搭建 我的git截图我使用的datagrip 运行sql学习到jwt令牌一种新的配置方式&#xff0c;写配置文件学习到了build属性nginx解决跨域的问题2.导入接口的文档 结果如图所示 3.Swagger /*** 通过knife4j生成接口文档* return*/Beanpublic Docket docket() {ApiInfo api…

每日学习总结20240219

每日总结 20240219 1.文件类型.csv CSV文件是一种以逗号分隔值&#xff08;Comma-Separated Values&#xff09;为标记的文本文件&#xff0c;它可以用来存储表格数据。每一行表示一条记录&#xff0c;而每一条记录中的字段则使用逗号或其他特定的分隔符进行分隔。 常用场景…

vector容器

1. vector基本概念 1.1 功能&#xff1a; vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector与普通数组区别&#xff1a; 不同之处在于数组是静态空间&#xff0c;而vector可以动态扩展 动态扩展&#xff1a; 并不是在原空间之后续接新空间&#xff0c;而是找更…

详解平面点云面积计算

部分代码展示&#xff1a; &#xff08;1&#xff09;利用格网法计算面积&#xff1a; //&#xff08;2&#xff09;测试使用格网法计算平面点云面积 void main() {char *inputpath "D:\\testdata\\data.txt";vector<pcl::PointXYZ> points ReadPointXYZIn…

从入门到精通:AI绘画与修图实战指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在这篇文章中&#xff0c;我们将深入探讨如何利…

蓝桥杯嵌入式第10届真题(完成) STM32G431

蓝桥杯嵌入式第10届真题(完成) STM32G431 题目 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body********************************…

应急响应实战笔记02日志分析篇(5)

第5篇:MySQL日志分析 常见的数据库攻击包括弱口令、SQL注入、提升权限、窃取备份等。对数据库日志进行分析&#xff0c;可以发现攻击行为&#xff0c;进一步还原攻击场景及追溯攻击源。 0x01 Mysql日志分析 general query log能记录成功连接和每次执行的查询&#xff0c;我们…

Linux环境变量配置文件--《一图胜千言》

这张图是一个关于Linux系统中shell启动时配置文件加载顺序的流程图。图中分为登录shell和非登录shell两种情况&#xff0c;来描述不同配置文件的读取过程。 登录shell&#xff1a; 当用户登录时&#xff0c;会首先检查是否存在/etc/profile文件&#xff0c;如果存在&#xff0c…

华为配置旁挂二层组网直接转发示例

配置旁挂二层组网直接转发示例 组网图形 图1 配置旁挂二层组网直接转发示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件扩展阅读 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff…
推荐文章