diff --git a/README.md b/README.md index 5f0fba7..e928c72 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,23 @@ 赫蹏(hètí)是专为中文内容展示设计的排版样式增强。它基于通行的中文排版规范而来,可以为网站的读者带来更好的文章阅读体验。 +预览:[https://sivan.github.io/heti/](https://sivan.github.io/heti/) + 主要特性: - 全标签样式统一; - 贴合网格的排版; -- 内置多种预设字体族(仅限桌面端); -- 支持横排、竖排两种排版; -- 支持诗词、行间注版式; -- 兼容 *normalize.css*、**CSS Reset** 等大部分重置样式; +- 预置多种预设字体族(仅限桌面端); +- 预置横排、直排(竖排)样式; +- 预置古文、诗词样式; +- 预置行间注排版样式; +- 预置多栏排版样式; +- 兼容 *normalize.css*、*CSS Reset* 等常见样式重置; - 移动端支持; +- 基于 BEM; - …… +总之,用上就会变好看。 + ## 使用方法 1. 在页面的 `` 标签中引入 `heti.css` 文件: diff --git a/lib/_base.scss b/lib/_base.scss index 502ae13..80e5145 100644 --- a/lib/_base.scss +++ b/lib/_base.scss @@ -63,12 +63,8 @@ text-align: justify; @include non-cjk-block { - text-align: left; + text-align: start; } - - //+ pre { - // margin-block-start: -$std-block-unit / 2; - //} } pre { @@ -81,6 +77,7 @@ padding-inline-start: $std-inline-unit; padding-inline-end: $std-inline-unit; overflow: auto; + font-family: $font-family-mono; white-space: pre; word-wrap: normal; background-color: rgba(0, 0, 0, 0.054); diff --git a/lib/_heading.scss b/lib/_heading.scss index 4462bd1..67b3718 100644 --- a/lib/_heading.scss +++ b/lib/_heading.scss @@ -15,6 +15,7 @@ // 顶边距默认为一行间距,且不因边距重叠原因减半 // 底边距考虑到亲密性,默认为半行间距 + margin: 0; margin-block-start: $std-block-unit; margin-block-end: $std-block-unit / 2; font-weight: $font-weight-bold; diff --git a/lib/_helper-inline.scss b/lib/_helper-inline.scss deleted file mode 100644 index e7403ab..0000000 --- a/lib/_helper-inline.scss +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Author: Sivan [sun.sivan@gmail.com] - * Description: define inline helper classes. - */ -@import "variables"; - -@mixin hetiInlineHelperClasses { - // 标题内锚点 - #{$root-selector}-anchor { - position: absolute; - left: -1em; - width: 1em; - font-family: $font-family-hei; - font-weight: 400; - line-height: inherit; - text-align: center; - opacity: 0; - transition: opacity 0.2s linear; - - &:hover { - text-decoration: none; - border-block-end: 0; - } - - @at-root { - #{$root-selector} { - h1, - h2, - h3, - h4, - h5, - h6 { - position: relative; - - &:hover #{$root-selector}-anchor { - opacity: 1; - } - } - } - } - } - - // @todo: 用于标点悬挂用的样式 - #{$root-selector}-hang { - @include hang(); - } -} diff --git a/lib/_inline.scss b/lib/_inline.scss index 2fc1ad2..4904b82 100644 --- a/lib/_inline.scss +++ b/lib/_inline.scss @@ -35,7 +35,7 @@ dfn { font-weight: $font-weight-bold; - // 非中文时显示斜体 + // 非中文时不加粗 @include non-cjk-block { font-weight: $font-weight-normal; } @@ -110,6 +110,7 @@ margin-inline-start: 0.25em; margin-inline-end: 0.25em; font-size: 0.75em; + font-family: $font-family-hei; line-height: 1; vertical-align: baseline; } diff --git a/lib/_list.scss b/lib/_list.scss index 82a4174..70c88df 100644 --- a/lib/_list.scss +++ b/lib/_list.scss @@ -24,6 +24,7 @@ } } + /* 兼容性处理 */ // 重置部分 CSS Reset 中 ul, ol { list-style: none; } 造成的样式污染 // 如果搭配 normalize.css 使用,则不存在这些样式污染 @if $_css-reset-scheme == "reset" { diff --git a/lib/_modifier-layout.scss b/lib/_modifier-layout.scss deleted file mode 100644 index c58a135..0000000 --- a/lib/_modifier-layout.scss +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Author: Sivan [sun.sivan@gmail.com] - * Description: define vertical layout classes. - */ -@import "variables"; - -@mixin hetiLayoutModifier { - // 定义垂直布局 - &-vertical { - max-width: none; - max-height: $line-length; - writing-mode: vertical-rl; - letter-spacing: 0.125em; - } - - // 定义古文、诗词样式 - &-poetry, - &-ancient { - font-family: $font-family-song; - - h1, - h2, - h3 { - font-family: $font-family-song; - font-weight: $font-weight-bolder; - text-align: center; - - // 标题内元信息,不应占据空间影响标题文字居中 - #{$root-selector}-meta { - display: block; - font-weight: 400; - - @media screen and (min-width: 640px) { - @include hang(); - - display: inline; - margin-block-start: 4px; - margin-inline-start: 8px; - } - } - } - - #{$root-selector}-verse { - text-align: center; - text-indent: 0; - } - - // 古文(文言文、词)默认首行缩进 - p { - text-indent: $text-indent-length; - } - } - - // 定义行间注样式 - // @todo: 类名太长了,得简化一下 - &-interlinear-annotation { - // 首行缩进且行间距大,无需添加段落边距 - p { - margin-block-start: 0; - margin-block-end: 0; - line-height: $line-height-expanded-ultra; - text-indent: $text-indent-length; - } - - // 着重号不应影响行间距,经测试最小可用行高为 1.7 - em { - -webkit-text-emphasis: filled circle; - -webkit-text-emphasis-position: under; - font-weight: $font-weight-normal; - - @include non-cjk-block { - -webkit-text-emphasis: none; - } - } - - // ruby 不应影响行间距,经测试最小可用行高为 2 - //ruby {} - } -} diff --git a/lib/_table.scss b/lib/_table.scss index eb2f7f8..0c0c7cd 100644 --- a/lib/_table.scss +++ b/lib/_table.scss @@ -1,6 +1,6 @@ /** * Author: Sivan [sun.sivan@gmail.com] - * Description: 表格样式 + * Description: table styles. */ @import "variables"; @@ -24,6 +24,8 @@ caption { caption-side: bottom; + margin-block-start: 2px; + margin-block-end: -4px; font-size: $font-size-small; line-height: $line-height-size-small; } diff --git a/lib/_variables.scss b/lib/_variables.scss index 0e40d06..cd88303 100644 --- a/lib/_variables.scss +++ b/lib/_variables.scss @@ -6,29 +6,29 @@ // 定义赫蹏根 class 名 $root-selector: '.heti' !default; -// 字体 Fonts -/// 字体栈 Font Stacks -$_font-stack-hei: "Pingfang SC", "Pingfang TC", "Heiti SC", "Heiti TC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei" !default; -$_font-stack-song: 'Noto Serif','Noto Serif CJK SC', 'Noto Serif CJK', 'Source Han Serif SC', ‘Source Han Serif’, source-han-serif-sc, "Songti SC", "Songti TC", STSong, SimSun !default; +/* 字体 Fonts */ +// 字体栈 Font Stacks +$_font-stack-hei: "Pingfang SC", "Heiti SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei" !default; +$_font-stack-song: "Songti SC", STSong, SimSun !default; $_font-stack-kai: "Kaiti SC", STKaiti !default; $_font-stack-sans: "Helvetica Neue", Helvetica, Arial !default; $_font-stack-serif: "Times New Roman", Times !default; $_font-stack-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier !default; $_font-stack-symbol: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; -/// 字体族 Font Families +// 字体族 Font Families $font-family-hei: $_font-stack-sans, $_font-stack-hei, sans-serif, $_font-stack-symbol !default; $font-family-song: $_font-stack-serif, $_font-stack-song, serif, $_font-stack-symbol !default; $font-family-kai: $_font-stack-serif, $_font-stack-kai, serif, $_font-stack-symbol !default; $font-family-mono: $_font-stack-mono, monospace, $_font-stack-symbol !default; -/// 字重 Font Weights +// 字重 Font Weights $font-weight-bolder: 800 !default; $font-weight-bold: 600 !default; $font-weight-normal: 400 !default; $font-weight-lighter: 200 !default; -/// 字号 Font Sizes +// 字号 Font Sizes $font-size-normal: 16px !default; $font-size-x-large: 20px !default; $font-size-large: 18px !default; @@ -42,6 +42,7 @@ $font-size-h4: 18px !default; $font-size-h5: 16px !default; $font-size-h6: 14px !default; +/* 行 Lines */ // 行宽 $line-length: 42em !default; @@ -64,6 +65,7 @@ $line-height-size-h4: 24px !default; $line-height-size-h5: 24px !default; $line-height-size-h6: 24px !default; +/* 段落 Paragraphs */ // 标准网格单位变量 Standard Length // 垂直方向标准单位 = 标准行高 // 水平方向标准单位 = 标准字号 @@ -73,13 +75,18 @@ $std-inline-unit: $font-size-normal !default; // 示例:缩进单位 = 二倍文字宽度 $text-indent-length: 2em !default; -// 开发用配置项 Develop Configs +/* 栏 Columns */ +// 分栏 +$column-count-list: (1, 2, 3, 4) !default; +$column-width-list: (16em, 20em, 24em, 28em, 32em, 36em, 40em, 44em, 48em) !default; -/// 预设重置方案 "reset" | "normalize" -/// reset:假定 Eric Meyer 的 CSS Reset 或其它流行的 Reset -/// normalize:指定为 normalize.css +/* 开发用配置项 Develop Configs */ +// 预设重置方案 +// `reset`:假定 Eric Meyer 的 CSS Reset 或其它流行的 Reset +// `normalize`:指定为 normalize.css $_css-reset-scheme: "reset"; +/* 混合 Mix-ins */ // Mix-in: Clear float @mixin clear-float { &::before, @@ -105,4 +112,18 @@ $_css-reset-scheme: "reset"; @mixin hang { position: absolute; line-height: inherit; + text-indent: 0; +} + +/* 函数 Functions */ +// Function: batch prefix/suffix list-item +// batch-fix-list((2, 3), '#{$root-selector}--columns-') => (.heti--columns-2, .heti--columns-3) +@function batch-fix-list($list, $prefix: '', $suffix: '') { + $_list: () !default; + + @each $item in $list { + $_list: append($_list, #{$prefix}#{$item}#{$suffix}, comma); + } + + @return $_list; } diff --git a/lib/_helper-block.scss b/lib/helpers/_block.scss similarity index 51% rename from lib/_helper-block.scss rename to lib/helpers/_block.scss index 5f8e482..2eee34f 100644 --- a/lib/_helper-block.scss +++ b/lib/helpers/_block.scss @@ -2,9 +2,46 @@ * Author: Sivan [sun.sivan@gmail.com] * Description: define block helper classes. */ -@import "variables"; +@import "../variables"; @mixin hetiBlockHelperClasses { + /* 段落相关 */ + // 元信息无缩进 + #{$root-selector}-meta { + display: block; + text-indent: 0; + } + + // 诗节无缩进,居中显示 + #{$root-selector}-verse { + text-align: center; + text-indent: 0; + } + + // 定义扩展字号 + #{$root-selector} { + &-large { + font-size: $font-size-large; + line-height: $line-height-size-large; + } + + &-x-large { + font-size: $font-size-x-large; + line-height: $line-height-size-x-large; + } + + &-small { + font-size: $font-size-small; + line-height: $line-height-size-small; + } + + &-x-small { + font-size: $font-size-x-small; + line-height: $line-height-size-x-small; + } + } + + /* 列表相关 */ // 定义拉丁字母的有序列表 #{$root-selector}-list-latin { list-style-type: upper-latin; @@ -30,30 +67,4 @@ } } } - - // 定义多栏布局 - @each $columns in (2, 3, 4) { - #{$root-selector}-columns-#{$columns} { - // 多行时不再设总宽度限制 - max-width: none; - column-count: #{$columns}; - column-gap: 2em; - } - } - - @each $column-width in (16em, 20em, 24em, 28em, 32em, 36em, 40em, 44em, 48em) { - #{$root-selector}-columns-#{$column-width} { - // 多行时不再设总宽度限制 - max-width: none; - column-width: #{$column-width}; - column-gap: 2em; - } - } - - // 元信息、诗节居中显示 - #{$root-selector}-meta { - line-height: $line-height-size-normal; - text-align: center; - text-indent: 0; - } } diff --git a/lib/helpers/_inline.scss b/lib/helpers/_inline.scss new file mode 100644 index 0000000..9dca81e --- /dev/null +++ b/lib/helpers/_inline.scss @@ -0,0 +1,22 @@ +/* + * Author: Sivan [sun.sivan@gmail.com] + * Description: define inline helper classes. + */ +@import "../variables"; + +@mixin hetiInlineHelperClasses { + // @todo: 用于标点悬挂用的样式 + #{$root-selector}-hang { + @include hang(); + } + + // 显示强烈的着重号 + #{$root-selector}-em { + -webkit-text-emphasis: filled circle; + -webkit-text-emphasis-position: under; + + @include non-cjk-block { + -webkit-text-emphasis: none; + } + } +} diff --git a/lib/heti.scss b/lib/heti.scss index 06b9b16..3d9f3d5 100644 --- a/lib/heti.scss +++ b/lib/heti.scss @@ -7,10 +7,13 @@ @import "list"; @import "table"; @import "inline"; -@import "modifier-layout"; -@import "modifier-font"; -@import "helper-block"; -@import "helper-inline"; +@import "modifiers/font-stack"; +@import "modifiers/writing-mode"; +@import "modifiers/column"; +@import "modifiers/ancient"; +@import "modifiers/annotation"; +@import "helpers/block"; +@import "helpers/inline"; #{$root-selector} { // 中文每行展示文字(CPL)建议在 30~50 之间,默认 42 @@ -24,18 +27,26 @@ // 自动在中西文间加 1/4 空格(暂无浏览器支持) //text-spacing: ideograph-alpha; - // 引入各模块 + // 模块引用顺序 + + // 1. 引入各模块 + // .heti h1, .heti p, .heti ul @include hetiBase(); @include hetiHeading(); @include hetiList(); @include hetiTable(); @include hetiInline(); - // 定义所有状态样式(与 .heti 并列使用) - @include hetiLayoutModifier(); + // 2. 定义所有修饰器(需与 .heti 组合使用) + // .heti--sans h1, .heti--vertical h1 etc. @include hetiFontModifier(); + @include hetiColumnModifier(); + @include hetiWritingModeModifier(); + @include hetiAncientModifier(); + @include hetiAnnotationModifier(); - // 定义所有内嵌样式(仅在 .heti 内使用有效) + // 3. 定义工具类样式(仅在 .heti 内部使用) + // .heti .heti-verse, .heti .heti-hang @include hetiBlockHelperClasses(); @include hetiInlineHelperClasses(); } diff --git a/lib/modifiers/ancient.scss b/lib/modifiers/ancient.scss new file mode 100644 index 0000000..4932a32 --- /dev/null +++ b/lib/modifiers/ancient.scss @@ -0,0 +1,60 @@ +/* + * Author: Sivan [sun.sivan@gmail.com] + * Description: define ancient styles. + */ +@import "../variables"; + +@mixin hetiAncientModifier { + // 定义古文、古诗样式 + &--ancient, + &--poetry { + // 古文、古诗用宋体(覆盖全局字体) + font-family: $font-family-song; + + // 古文标题用楷体(覆盖全局字体) + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: $font-family-kai; + font-weight: $font-weight-bolder; + text-align: center; + + // 标题内元信息仅在桌面端采取悬挂处理,且不占据空间影响文字居中 + #{$root-selector}-meta { + font-weight: 400; + + @media screen and (min-width: 640px) { + @include hang(); + + display: inline; + margin-block-start: 4px; + margin-inline-start: 8px; + } + } + } + + #{$root-selector}-meta { + line-height: $line-height-size-normal; + text-align: center; + text-indent: 0; + } + } + + &--ancient { + // 古文(文言文、词)首行缩进 + p { + text-indent: $text-indent-length; + } + } + + &--poetry { + // 诗节无缩进,居中显示 + p { + text-align: center; + text-indent: 0; + } + } +} diff --git a/lib/modifiers/annotation.scss b/lib/modifiers/annotation.scss new file mode 100644 index 0000000..6a51150 --- /dev/null +++ b/lib/modifiers/annotation.scss @@ -0,0 +1,37 @@ +/* + * Author: Sivan [sun.sivan@gmail.com] + * Description: define interlinear annotation styles. + */ +@import "../variables"; + +@mixin hetiAnnotationModifier { + &--annotation { + // 首行缩进且行间距加大,去除段落间距 + p { + margin-block-start: 0; + margin-block-end: 0; + line-height: $line-height-expanded-ultra; + text-indent: $text-indent-length; + } + + // 着重号不应影响行间距,经测试最小可用行高为 1.7 + em { + -webkit-text-emphasis: filled circle; + -webkit-text-emphasis-position: under; + font-weight: $font-weight-normal; + + @include non-cjk-block { + -webkit-text-emphasis: none; + } + } + + // 元信息保持间距 + #{$root-selector}-meta { + margin-block-start: $std-block-unit / 2; + margin-block-end: $std-block-unit; + } + + // ruby 不应影响行间距,经测试最小可用行高为 2 + //ruby {} + } +} diff --git a/lib/modifiers/column.scss b/lib/modifiers/column.scss new file mode 100644 index 0000000..6c6d11b --- /dev/null +++ b/lib/modifiers/column.scss @@ -0,0 +1,35 @@ +/* + * Author: Sivan [sun.sivan@gmail.com] + * Description: define column styles. + */ +@import "../variables"; + +@mixin hetiColumnModifier { + // 定义多栏排版 + $selector-list: batch-fix-list(join($column-count-list, $column-width-list), '&--columns-'); + + #{join($selector-list, comma)} { + // 多行时不再设总宽度限制 + max-width: none; + column-gap: 2em; + + // 多栏排版时减半段间距 + p { + margin-block-start: $std-block-unit / 2 / 2; + margin-block-end: $std-block-unit / 2; + text-indent: $text-indent-length; + } + } + + @each $columns in $column-count-list { + &--columns-#{$columns} { + column-count: #{$columns}; + } + } + + @each $column-width in $column-width-list { + &--columns-#{$column-width} { + column-width: #{$column-width}; + } + } +} diff --git a/lib/_modifier-font.scss b/lib/modifiers/font-stack.scss similarity index 50% rename from lib/_modifier-font.scss rename to lib/modifiers/font-stack.scss index 2bddb9a..f8fd8f2 100644 --- a/lib/_modifier-font.scss +++ b/lib/modifiers/font-stack.scss @@ -1,22 +1,25 @@ /* * Author: Sivan [sun.sivan@gmail.com] - * Description: define font stack classes. + * Description: define global font stacks. */ -@import "variables"; +@import "../variables"; @mixin hetiFontModifier { + // 定义默认采用无衬线字体 // 定义无衬线字体为黑体 - &-sans { + &, + &--sans { font-family: $font-family-hei; } // 定义衬线字体为宋体 - &-serif { + &--serif { font-family: $font-family-song; } // 定义传统字体 - &-classic { + &--classic { + // 正文使用宋体 font-family: $font-family-song; // 标题使用 800 字重 @@ -42,37 +45,11 @@ font-family: $font-family-kai; } - // 说明文字、角标、表头使用黑体 + // 说明文字、表头使用黑体 figcaption, caption, - sup, - sub, th { font-family: $font-family-hei; } } - - // 定义超大号字 - &-x-large { - font-size: $font-size-x-large; - line-height: $line-height-size-x-large; - } - - // 定义大号字 - &-large { - font-size: $font-size-large; - line-height: $line-height-size-large; - } - - // 定义小号字 - &-small { - font-size: $font-size-small; - line-height: $line-height-size-small; - } - - // 定义超小号字 - &-x-small { - font-size: $font-size-x-small; - line-height: $line-height-size-x-small; - } } diff --git a/lib/modifiers/writing-mode.scss b/lib/modifiers/writing-mode.scss new file mode 100644 index 0000000..f2f587c --- /dev/null +++ b/lib/modifiers/writing-mode.scss @@ -0,0 +1,24 @@ +/* + * Author: Sivan [sun.sivan@gmail.com] + * Description: define writing mode styles. + */ +@import "../variables"; + +@mixin hetiWritingModeModifier { + // 定义垂直布局 + &--vertical { + max-width: none; + max-height: $line-length; + writing-mode: vertical-rl; + letter-spacing: 0.125em; + + h1, + h2, + h3, + h4, + h5, + h6 { + text-align: start; + } + } +} diff --git a/package.json b/package.json index fe735b0..55ba5e1 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "lib": "lib" }, "scripts": { - "start": "node-sass -w --output-style=compressed index.scss dist/heti.css", + "start": "node-sass -w --output-style=nested index.scss dist/heti.css", "build": "node-sass index.scss dist/heti.css --output-style=compressed", "deploy": "gh-pages -d dist", "test": "npx stylelint --config .stylelintrc 'lib/**/*.scss'"