npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cssin

v2.0.0

Published

> cssin 2.0 删减了许多API,要使用原有版本,请使用 master/tag/1.6.7 版本

Downloads

140

Readme

cssin 2.0 删减了许多API,要使用原有版本,请使用 master/tag/1.6.7 版本

我们先看看我们最终的目标, 我们可以如何描述代码:

原生JS用法:

const view = document.createElement('div');

cssin`bg:#f00; @m:display:none; hover:radius:8px; radius:4px`(view);

React用法:

import React from "react";

export default () => (
  <button className={cssin`bg:#f00; @m:display:none; hover:radius:8px; radius:4px`}>
    我是一个按钮
  </button>
);

或者:

import React from "react";

export default () => (
  <button cssin="bg:#f00; @m:display:none; hover:radius:8px; radius:4px">
    我是一个按钮
  </button>
);

在这个文件中,我们 "似乎没有引入任何库",就好像写内联样式一样,把样式描述、媒体查询、伪类都实现了, 并且可自定义样式名,如 bg、radius。

cssin

cssin 是一个高度可定制的低级 CSS-In-JS 框架,它为您提供构建定制设计所需的所有构建模块,而无需任何令人讨厌的样式,你可以使用内联样式的所有语法,和其他扩展语法。

大多数 CSS 框架都做得太多了。 它们带有各种预先设计的组件,如按钮,卡片和警报,这些组件可能会帮助您最初快速移动,但是当您的网站使用自定义设计脱颖而出时,会导致更多的痛苦。

cssin 与众不同。

cssin 提供了低级实用程序类,而不是固定的预先设计的组件,使您可以构建完全自定义的设计而无需离开 JS。

cssin 生成的每个相同的样式值可以被重复引用,而不是重新创建。

理念

我们在使用 cssin 之前做了非常多的尝试,css\less\scss, tailwindCSS, styled-components 和其他 css-in-js 方案。其中 tailwindCSS 是最符合生产需要的,我们从中学到许多东西和理念;可是这些样式方案对于作者来说并没能真正解决问题:

简短高效的描述我的样式,并且不离开 js;当然也不放弃 css 的任何一个特性

css-in 就是为了解决此类问题而存在

旨在定制

cssin 所有样式都是通过定制而得,cssin 允许您自定义它。这包括颜色,边框大小,字体粗细,间距实用程序,断点,阴影和任何 css 样式。

cssin 采用纯 Typescript 编写,并且无需对项目框架进行配置,这意味着您可以轻松获得真正编程语言的全部功能。

cssin 相当于在内敛样式上扩展了伪类和媒体查询,并且支持自定义属性名和设定组件。

cssin 不仅仅是一个 CSS-IN-JS 框架,它还是一个创建设计系统的引擎。

轻巧

  • 仅有 2kb (gzip)
  • 每条样式会被缓存, 以更高的性能进行样式处理
  • 可以在任何框架中使用,如你喜欢的 React、Vue、Stencil

安装

$ npm i cssin --save

先看看展现形式

example: navar.workos.top

在没有进行任何配置之前,cssin 的语法和内敛样式是一致的

import React from "react";
import cssin from "cssin";

// 设置一个全局的 css-value
document.body.style.setProperty("--button-color", "#fff");

export default () => {
  return (
    <div cssin="background-color:#f66; hover:background-color:#f33; padding:8px; color:#000; border:2px solid #f33; @m:border-radius:4px;">
      Button
    </div>
  );
};

看起来还不错,有点像内联样式,但是又有些许不同,似乎直接描述了伪类和媒体查询,而且代码不够精简。

好的,我们最后会通过简单的配置的让样式描述变成这样:

import React from "react";
import cssin from "cssin";

export default () => {
  return (
    <div className={cssin`btn:#f33, 8px; hover:bg:#f33; @m:radius:4px;`}>
      Button
    </div>
  );
};

或者极限简洁:

import React from 'react';
import cssin from 'cssin';

export default () => {
  return <div cssin="button"}>Button</div>;
};

我们会一步步来达到最后的步骤。

或许一段话就可以描述清楚 cssin

我们先回顾刚开始的代码块:

export default () => {
  return (
    <div cssin="background-color:#f66; hover:background-color:#f33; padding:8px; color:--button-color; border:2px solid #f33; @m:border-radius:4px;">
      Button
    </div>
  );
};

上述代码有点像内联样式,但是又有一些不同,因为它可以实现伪类及更好的自定义,我们逐步分析:

  • 和编写内联样式一样的编写 css 样式, 如: background-color: #f66; padding: 4px;
  • 直接使用伪类, 伪类在属性名之前,使用:分割如: hover:background-color=#f33
  • 可以直接描述媒体查询等功能, 媒体查询对象使用@开头, 如: @m:border-radius=4px

其他规则:

  • 如果只有属性名,那么它将是一个组件, 如 button;
  • 如果值是一个单一的 css 变量, 如 color:--button-color; 等效于 color:var(--button-color);
  • 使用!表示!important, 如 color: #f00!; 等效于 color: #f00 !important
  • 如果只有属性名,并且以 . 开头, 那么就是对原生 css 样式的引用, 如 .button;
  • 如果包含 {}, 表示这是一个纯 css, 它会被插入至全局样式中, 如 body { margin:0px; }

以上就是 cssin 的所有规则

下面是完整属性的表达式: @[媒体查询]:[伪类名]:[属性名]:[属性值];

下面这句完整的语法描述:

// 当媒体查询大于 760px 时、鼠标移入时、描边等于 #f00;
cssin`@m:hover:border:1px solid #f00;`;

为什么不直接编写 style 内联样式?

  1. style 样式无法完全描述 css 的功能,如媒体查询、伪类等等 style;
  2. 样式无法自定义更简短的样式集、样式集的组合、嵌套;
  3. 内联样式无法直接引用 className,这样我们通常需要编写 css 文件,设置 className 和 style;
  4. 并且默认优先级比 css 高,css 和 内联样式混合使用需要注意优先级;

cssin 最后生成的还是 css 样式,所以不会有以上的问题

如果更喜欢编写 style 属性

有的朋友更喜欢编写 style 属性,但是 style 中的一个痛点是无法实现伪类或媒体查询。

cssin 足够轻量,我们也可以仅仅使用它的伪类或媒体查询特性,来配合 style 属性进行项目样式的编写.

不过我们要注意,style 中编写的属性权重默认高于 className 中的样式,所以需要添加 !important:

import React from "react";
import cssin from "cssin";


export default () => {
  return (
    <div
      cssin="hover:background:#f00 !important;"
      style={{
        background: "#00f",
        fontSize: "20px"
      }}
    >
      Button
    </div>
  );
};

由于这个模式很常见,所以在 cssin 中,它可以使用 ! 直接表示 !important:

...
export default () => {
  return (
    <div
      cssin="hover:background:#f00!"
      style={{
        background: "#00f",
        fontSize: "20px"
      }}
    >
      Button
    </div>
  );
};Z

订制自定义样式

和众多 css 框架一样,cssin 允许你自定义样式集,这样可以用更简短的声明来描述样式

cssin 有一个 addSheets 属性用来添加样式映射表

我们现在达成刚刚的约定,将:

background-color:#f66; hover:background-color:#f33; padding:4px; color:--button-color; border:2px solid #f33; @m:border-radius:8px;

变成:

btn:#f33, 4px; hover:bg:#f33; @m:radius:8px;

import React from 'react';
import cssin, { addSheets } from 'cssin';

// 添加自定义样式集
addSheets({
  bg: (v) => `{ background-color: ${v}; }`,
  radius: (v) => `{ border-radius: ${v}; }`,
  btn: (v) => {
    const values = v.split(';');
    return {
      `{ background-color: ${values[0]}; padding:${values[1]}; color:var(--button-color); }`
    }
  },
});

// 使用自定义的样式
export default () => {
  return <div cssin="btn:#f33, 4px; hover:bg:#f33; @m:radius:8px">Button</div>;
};

由于使用 cssin , 我们不会需要有 css 代码,所以可以降低项目首屏的资源请求。

自定义样式除了可以简化开发,还可以减少 js 代码量,从而最终达到相对更少的打包资源。

订制媒体查询

cssin 默认配置了 4 个尺寸级别的媒体查询,和基于设备媒体查询,我们可以覆盖它或者创建新的规则

注意,我们约定,只有以 @ 开头的才是媒体查询对象

// 默认的媒体查询
const max = "@media (max-width: ";
const min = "@media (min-width: ";

addSheets({
  "@xs": (v: string) => `${max}640px){${v}}`,
  "@s": (v: string) => `${max}720px){${v}}`,
  "@m": (v: string) => `${max}1024px){${v}}`,
  "@l": (v: string) => `${max}1280px){${v}}`,
  "@xl": (v: string) => `${max}1920px){${v}}`,
  "@!xs": (v: string) => `${min} 640px){${v}}`,
  "@!s": (v: string) => `${min}720px){${v}}`,
  "@!m": (v: string) => `${min}1024px){${v}}`,
  "@!l": (v: string) => `${min}1280px){${v}}`,
  "@!xl": (v: string) => `${min}1920px){${v}}`,
  "@ios": (v: string) => `${min}${os.isIOS ? "0px" : "9999px"}){${v}}`,
  "@android": (v: string) => `${min}${os.isAndroid ? "0px" : "9999px"}){${v}}`,
  "@pc": (v: string) => `${min}${os.isPc ? "0px" : "9999px"}) {${v}}`,
  "@mobile": (v: string) => `${min}${os.isMobile ? "0px" : "9999px"}){${v}}`
});
// 我们覆盖 @m 以及创建一个 @xxl
addSheets({
  "@m": v => `@media (min-width: 800px) {${v}}`,
  "@xl": v => `@media (min-width: 1920px) {${v}}`
});

使用媒体查询,以下例子是屏幕宽度大于 800px,button 宽度为 200px,并且在 native 端隐藏

import React from "react";
// 最终只需要包裹一个单词的声明
export default () => {
  return (
    <div cssin="width:100px; height:50px; @m:width:200px; @native:display:none;">
      Button
    </div>
  );
};

订制组件

我们希望把刚刚的代码简写成更精巧的组件, 组件其实是一组样式集

设置自定义组件, 因为 sheets 是一个简单的对象表,请注意不要和其他自定义样式重名导致覆盖

它和自定义样式或媒体查询的区别是它的值是一个单纯的字符串:

import React from "react";
import { addSheets } from "cssin";

addSheets({
  // 区别于自定义样式,组件的值是一个字符串,它遵循 cssin 语法,可以调用其他组件和自定义样式
  button: "bgc:#f66; hover:bgc:#f22; padding:8px; color:--button-color;"
});

// 最终只需要包裹一个单词的声明
export default () => {
  return <div cssin="button">Button</div>;
};

注意,组件不可以和伪类或者媒体查询进行组合,因为组件内部就已经包含了伪类或媒体查询

性能开销

cssin 虽然是运行时创建 css 样式,但是它有着极低的性能开销。

我们可以看到,创建重复执行 500 次,每次大约创建 20 条样式,只消耗了 1.6ms, 这是因为 cssin 会对整体属性做缓存,还会对子属性创建 css 样式做缓存:

console.time(t);
for (let i = 0; i < 500; i++) {
  cssin(
    `transition:all 0.1s ease-in; box-shadow:--shadow-1lg; hover:box-shadow:--shadow-1md; active:box-shadow:--shadow-sm1;`
  );
  cssin(
    `transition:all 0.2s ease-in; box-shadow:--shadow-2lg; hover:box-shadow:--shadow-2md; active:box-shadow:--shadow-sm2;`
  );
  cssin(
    `transition:all 0.3s ease-in; box-shadow:--shadow-3lg; hover:box-shadow:--shadow-3md; active:box-shadow:--shadow-sm3;`
  );
  cssin(
    `transition:all 0.4s ease-in; box-shadow:--shadow-4lg; hover:box-shadow:--shadow-4md; active:box-shadow:--shadow-sm4;`
  );
}
console.timeEnd(t); // 1.60009765625ms

现在开始使用它:

$ npm i cssin --save

盼望 Star 或提出贡献,仓库地址:

github.com/ymzuiku/cssin