{"id":13756750,"url":"https://github.com/cssdream/cssgrace","last_synced_at":"2025-07-26T21:11:15.728Z","repository":{"id":25240113,"uuid":"28664808","full_name":"cssdream/cssgrace","owner":"cssdream","description":"从今天起，写简单优雅面向未来的 CSS。From now on,writing brief,elegant,future-oriented CSS.","archived":false,"fork":false,"pushed_at":"2022-10-26T06:57:10.000Z","size":434,"stargazers_count":593,"open_issues_count":26,"forks_count":63,"subscribers_count":36,"default_branch":"master","last_synced_at":"2025-07-06T00:08:27.589Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cssdream.png","metadata":{"files":{"readme":"README-zh.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-31T11:49:00.000Z","updated_at":"2024-12-31T16:02:39.000Z","dependencies_parsed_at":"2022-08-23T04:10:21.870Z","dependency_job_id":null,"html_url":"https://github.com/cssdream/cssgrace","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/cssdream/cssgrace","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssdream%2Fcssgrace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssdream%2Fcssgrace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssdream%2Fcssgrace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssdream%2Fcssgrace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cssdream","download_url":"https://codeload.github.com/cssdream/cssgrace/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssdream%2Fcssgrace/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267236822,"owners_count":24057657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T11:00:52.852Z","updated_at":"2025-07-26T21:11:15.705Z","avatar_url":"https://github.com/cssdream.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# CSS Grace\n\n[![Build Status](https://img.shields.io/travis/cssdream/cssgrace/master.svg?label=Unix%20build)](https://travis-ci.org/cssdream/cssgrace) \n[![Windows Build status](https://img.shields.io/appveyor/ci/yisibl/cssgrace/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/yisibl/cssgrace/branch/master) \n[![NPM Downloads](https://img.shields.io/npm/dm/cssgrace.svg?style=flat)](https://www.npmjs.com/package/cssgrace) \n[![NPM Version](http://img.shields.io/npm/v/cssgrace.svg?style=flat)](https://www.npmjs.com/package/cssgrace) \n[![License](https://img.shields.io/npm/l/cssgrace.svg?style=flat)](http://opensource.org/licenses/MIT)  \n\n  \u003e**从今天起，写简单优雅面向未来的 CSS。**\n\n--------------\n\n[English](README.md)\n\nCSS Grace 是一个由 PostCSS 驱动，面向未来的 CSS 后处理工具。实现了大部分常用的 IE Hack，获取图片宽高等，position: center 等功能。同时可以配合 Sass/Less 等预处理工具使用，最重要的是它不改变 CSS 原生的语法，让 CSS 写起来更简单，更优雅。\n\n\n![CSS Grace 动画演示](http://gtms03.alicdn.com/tps/i3/TB1OXJaGpXXXXbbXFXXZ.oU0pXX-848-504.gif)\n\n\n* 向前，CSS Grace 可以作为一种 Polyfill 工具，让你可以提前使用一些 CSS3 的新特性。\n* 向后，CSS Grace 可以生成兼容旧浏览器的各种 Hack，让你无需担忧兼容性。\n* 而你，只用书写和关心标准的 CSS 语法。\n\n怎么样，可攻可受吧！\n\n![post and pre](test/img/post-and-pre.png)\n\n\n例如，骚年们会经常用下面这段 CSS 用来解决闭合浮动的问题：\n\n```css\n.clearfix {\n  *zoom: 1;\n}\n.clearfix:after {\n  clear: both;\n}\n.clearfix:before,\n.clearfix:after {\n  content: '';\n  display: table;\n}\n```\n\n这个语法糖虽然好用，兼容性良好，但在 HTML 中会出现非常多的 `class=\"clearfix\"`。甚至有些地方已经闭合了浮动，有些人为了保险起见，还是随手加上了`class=\"clearfix\"`。o(╯□╰)o\n\n如此一来代码显得尤为冗余，而且加了很多无语意的 class。更进一步，我们知道如果触发了 BFC 的元素是自带闭合浮动特性的，clearfix 君略感违和。\n\nQ: 那么，CSS Grace 如何解决呢？\n\n\u003e A: 直接使用 `clear: fix` 即可。\n\ninput:\n\n```css\n.foo {\n  clear: fix;\n}\n```\n\noutput:\n\n```css\n.foo {\n  *zoom: 1;\n}\n.foo:after {\n  clear: both;\n}\n.foo:before,\n.foo:after {\n  content: '';\n  display: table;\n}\n```\n\nQ: 那么，如何解决冗余问题呢？\n\n\u003e A: 还是直接使用 `clear: fix` 即可，\\(^o^)/~\n\n智能识别，如果存在触发 BFC 的属性，不生成语法糖。\n\ninput:\n\n```css\n.foo {\n  clear: fix;\n  overflow: hidden; /* 已经可以闭合浮动了 */\n}\n```\n\noutput:\n\n```css\n.foo {\n  overflow: hidden; /* 已经可以闭合浮动了 */\n}\n```\n\n就是那么任性！\n\n目前功能处于初步阶段，欢迎大家提出更多意见和想法。\n\n\n## 快速开始\n\n1. 下载并安装 Node.js\n\n2. 新建一个目录，比如 test ，在命令行中切换到该目录，安装 cssgrace。\n\n```console\nnpm install cssgrace\n```\n\n3. 在项目目录新增一个 test.js，代码如下：\n\n```console\nnpm install chokidar\n```\n\n```js\nvar fs       = require('fs')\nvar cssgrace = require('cssgrace')\n\nvar src = 'src/input.css'\nconsole.info('Watching…\\nModify the input.css and save.')\n\nchokidar.watch(src, {\n  ignored: /[\\/\\\\]\\./,\n  persistent: true\n}).on('all',\n  function(event, path, stats) {\n    var css = fs.readFileSync(src, 'utf8')\n    fs.writeFileSync('build/output.css', cssgrace.pack(css))\n  })\n```\n\n4. 在项目目录新增一个 input.css，注意编码要和 ```fs.readFileSync``` 中的保持一致。输入测试的 CSS 代码片段，比如：\n\n```css\n.foo::after {\n  position: center;\n  width: 210px;\n  height: 80px;\n  background: rgba(112, 26, 0, .3);\n}\n\n.bar {\n  display: inline-block;\n  opacity: .5;\n}\n```\n\n5. 在命令行中执行 `node test`，快去看看 output.css 中发生了什么吧！\n\n```css\n.foo:after {\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  margin-left: -105px;\n  margin-top: -40px;\n  width: 210px;\n  height: 80px;\n  background: rgba(112, 26, 0, .3);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4c701a00', endColorstr='#4c701a00');\n}\n\n:root .foo:after {\n  filter: none\\9;\n}\n\n.bar {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n  opacity: .5;\n  filter: alpha(opacity=50);\n}\n```\n\n-------------\n\n## 如何使用\n\n###  Node Watch \u0026 配合其他插件\n\n使用 chokidar 模块实时监测 CSS 文件变动，同时可以加载其他插件，灵活扩展。\n\n```js\nvar fs       = require('fs')\nvar chokidar = require('chokidar')\nvar postcss  = require('postcss')\nvar cssgrace = require('cssgrace')\nvar nested   = require('postcss-nested') //CSS 代码嵌套\nvar minmax   = require('postcss-media-minmax') //使用 \u003e=/\u003c= 代替 @media 中的 min-/max\nvar selector = require('postcss-custom-selectors') //自定义选择器\n\n\nvar src = 'src/input.css'\n\nconsole.info('Watching…\\nModify the input.css and save.')\n\n\nchokidar.watch(src, {\n  ignored: /[\\/\\\\]\\./,\n  persistent: true\n}).on('all',\n  function(event, path, stats) {\n    var css = fs.readFileSync(src, 'utf8')\n    var output = postcss()\n      .use(minmax())\n      .use(cssgrace)\n      .use(selector())\n      .use(nested)\n      .process(css)\n      .css;\n    fs.writeFileSync('build/output.css', output)\n  })\n```\n\n### Grunt\n\n```\nnpm install grunt-postcss\n```\n\n```js\nmodule.exports = function(grunt) {\n  grunt.initConfig({\n    pkg: grunt.file.readJSON('package.json'),\n    postcss: {\n      options: {\n        processors: [\n          require('postcss-custom-selector')(),\n          require('cssgrace'),\n        ]\n      },\n      dist: {\n        src: ['src/*.css'],\n        dest: 'build/grunt.css'\n      }\n    }\n  });\n\n  grunt.loadNpmTasks('grunt-contrib-uglify');\n  grunt.loadNpmTasks('grunt-postcss');\n\n  grunt.registerTask('default', ['postcss']);\n}\n```\n\n### Gulp\n\n```\nnpm install gulp-postcss\n```\n\n```js\nvar gulp = require('gulp');\nvar rename = require('gulp-rename');\nvar postcss = require('gulp-postcss');\nvar cssgrace = require('cssgrace');\nvar autoprefixer = require('autoprefixer-core')\n\ngulp.task('default', function () {\n    var processors = [\n        require('cssgrace')\n    ];\n    gulp.src('src/input.css')\n        .pipe(postcss(processors))\n        .pipe(rename('gulp.css'))\n        .pipe(gulp.dest('build'))\n});\ngulp.watch('src/*.css', ['default']);\n```\n\n## 更多功能\n\n### 自动生成 2x 背景图兼容代码\n\n现代浏览器中，可以使用标准的 `image-set()` 函数，会自动生成一段 Media Queries 来兼容不支持 `image-set()` 的浏览器。\n\ninput:\n\n```css\n.foo {\n  background-image: -webkit-image-set(\n                    url(../img/yuxifan@1x.jpg) 1x,\n                    url(../img/yuxifan@2x.jpg) 2x);\n}\n```\n\noutput:\n\n```css\n.foo {\n  background-image: url(../img/yuxifan@1x.jpg); /* Fallback */\n  background-image: -webkit-image-set(\n                    url(../img/yuxifan@1x.jpg) 1x,\n                    url(../img/yuxifan@2x.jpg) 2x);\n}\n\n@media only screen and (min-resolution: 2dppx) {\n  .foo {\n    background-image: url(../img/yuxifan@2x.jpg);\n    background-size: 320px 427px;\n}\n}\n```\n\n### 获取背景图宽高\n\n使用 `image-width` 和 `image-height` 获取图片的宽高。\n\n**注意：** url 和引号内的 image-width 和 image-height 不会被转换。\n\ninput:\n\n```css\n.foo {\n  background: url(../img/post-and-pre.png);\n  width: image-width;\n  height: image-height;\n}\n\n.foo {\n  background: url(../img/post-and-pre.png);\n  margin: image-width image-height -image-height;\n  content: 'image-width';\n}\n```\n\noutput:\n\n```css\n.foo {\n  background: url(../img/post-and-pre.png);\n  width: 720px;\n  height: 719px;\n}\n\n.foo {\n  background: url(../img/post-and-pre.png);\n  margin: 720px 719px -719px;\n  content: 'image-width';\n}\n```\n\n### position:center\n\n已知宽高元素居中，自动计算 margin 取值，麻麻再也不用担心我数学不好了。\n\ninput:\n\n```css\n.foo {\n  position: center;\n  width: 300px;\n  height: 123px;\n}\n```\n\noutput:\n\n```css\n.foo {\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  margin-left: -150px;\n  margin-top: -61.5px;\n  width: 300px;\n  height: 123px;\n}\n```\n\n### 修复常见错误\n\n#### 浮动或绝对定位元素不用写 display: block\n\n当存在 float: left|right 或者 position: absolute|fixed 时，会自动删除多余的 display: block|inline-block。\n\n\ninput:\n\n```css\n.foo {\n  position: absolute;\n  display: block;\n}\n\n.foo {\n  position: center;\n  display: block;\n}\n\n.foo {\n  float: left;\n  display: block;\n}\n```\n\noutput:\n\n```css\n.foo {\n  position: absolute;\n}\n\n.foo {\n  position: center;\n}\n\n.foo {\n  float: left;\n}\n```\n\n#### 绝对定位元素浮动不生效\n\n存在 position: absolute|fixed 时，会自动删除多余的 float: left|right。\n\ninput:\n\n```css\n.foo {\n  position: absolute;\n  float: left;\n}\n```\n\noutput:\n\n```css\n.foo {\n  position: absolute;\n}\n```\n\n### 自动补全漏写属性\n\n#### 自动修复 resize\n\nresize 生效 overflow 必须不是默认的 visible。\n\ninput:\n\n```css\n.foo {\n  resize: vertical;\n}\n\n.foo {\n  resize: both;\n  overflow: hidden;\n}\n```\n\noutput:\n\n```css\n.foo {\n  resize: vertical;\n  overflow: auto;\n}\n\n.foo {\n  resize: both;\n  overflow: hidden;\n}\n```\n\n#### 自动修复 text-overflow: ellipsis\n\ninput:\n\n```css\n.foo {\n  text-overflow: ellipsis;\n}\n\n.foo {\n  text-overflow: ellipsis;\n  overflow: auto;\n  white-space: normal;\n}\n\n```\n\noutput:\n\n```css\n.foo {\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n\n.foo {\n  text-overflow: ellipsis;\n  overflow: hidden;\n  white-space: nowrap;\n}\n```\n\n### IE Hack\n\n#### IE opacity\n\n自动生成 IE opacity filter。\n\ninput:\n\n```css\n.foo {\n  opacity: .6;\n}\n\n.foo {\n  opacity: 0.8293;\n}\n```\n\noutput:\n\n```css\n.foo {\n  opacity: .6;\n  filter: alpha(opacity=60);\n}\n\n.foo {\n  opacity: 0.8293;\n  filter: alpha(opacity=83);\n}\n```\n\n#### IE RGBA\n\n自动生成 IE RGBA filter。\n\n\u003e 由于 IE9 同时支持 filter 和 rgba，会导致颜色叠加，使用 IE9 + 支持的 `:root` 选择器去掉 IE9 中的 filter。\n\ninput:\n\n```css\n.foo {\n  background: rgba(153, 85, 102, 0.3);\n}\n```\n\noutput:\n\n```css\n.foo {\n  background: rgba(153, 85, 102, 0.3);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4c995566', endColorstr='#4c995566');\n}\n\n:root .foo {\n  filter: none\\9;\n}\n```\n\n#### IE inline-block\n\ninput:\n\n```css\n.foo {\n  display: inline-block;\n}\n```\n\noutput:\n\n```css\n.foo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n```\n\n## 贡献\n\n* 安装相关的依赖模块。\n* 尊重编码风格（安装 [EditorConfig](http://editorconfig.org/)）。\n* 在[test](test)目录添加测试用例。\n* 运行测试。\n\n```console\n$ git clone git@github.com:cssdream/cssgrace.git\n$ git checkout -b patch\n$ npm install\n$ npm test\n```\n\n## [Changelog](CHANGELOG.md)\n\n## [License](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcssdream%2Fcssgrace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcssdream%2Fcssgrace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcssdream%2Fcssgrace/lists"}