用JavaScript编写CSS

Sometimes programming is just using the right tool. This may be a framework, library or as it happens in my case CSS preprocessor. You probably don't realize it, but LESS or SASS have a lot of constraints. I managed to change that by writing my own CSS preprocessor. I stopped writing CSS and moved everything into the JavaScript world. This article is about AbsurdJS: a small Node.js module, which changed my workflow completely.

有时编程只是使用正确的工具。 这可能是框架,库,也可能是CSS预处理器。 您可能没有意识到,但是LESS或SASS有很多限制。 我设法通过编写自己CSS预处理程序来更改它。 我停止编写CSS,并将所有内容移入JavaScript世界。 本文是关于AbsurdJS的 :一个小的Node.js模块,它完全改变了我的工作流程。

这个概念 (The Concept)

Write your CSS with JavaScript

If you write a lot of CSS you probably use preprocessor. There are two popular - LESS and SASS. Both tools accept something, which looks like CSS, do some magic and export normal, pure CSS. What I did is just to replace the instrument and the input format. I didn't want to invent a new language or syntax, because this is connected with a lot of things like parsing and compiling. Thankfully, Node.js is here and I decided to use it. Also, I had a lot of LESS type projects, which means that I already use Node.js to compile my styles. It was much easier to replace a module instead of adding something completely new.

\

如果编写大量CSS,则可能使用预处理器。 流行有两种-LESS和SASS。 两种工具都可以接受类似于CSS的功能,可以执行一些魔术操作并输出普通的纯CSS。 我所做的只是替换乐器和输入格式。 我不想发明一种新的语言或语法,因为这与诸如解析和编译之类的许多事情有关。 幸运的是,Node.js在这里,我决定使用它。 另外,我有很多LESS类型的项目,这意味着我已经使用Node.js来编译我的样式。 更换模块比添加全新模块要容易得多。

\

输入 (The Input)

Write your CSS with JavaScript

I think that the closest thing to the CSS format is JSON -- that's what AbsurdJS accepts. Of course there are some cons of this transformation. You have to put some properties in quotes and of course the values. This needs a little bit more time during the writing, but as you will see below it's worth it.

我认为最接近CSS格式的是JSON,这就是AbsurdJS所接受的。 当然,这种转变也有一些弊端。 您必须在引号中加上一些属性,当然还要在值中加上一些属性。 在编写过程中,这需要花费更多时间,但是您将在下面看到,这是值得的。

一开始是...一个JavaScript文件 (In the Beginning was ... a JavaScript File)

Here is how a simple LESS file looks like:

这是一个简单的LESS文件的外观:

.main-nav {
    background: #333;
    color: #000;
    font-weight: bold;
    p {
        font-size: 20px;
    }
}

And here is its AbsurdJS equivalent. It's a simple Node.js module:

这是它的AbsurdJS等效项。 这是一个简单的Node.js模块:

module.exports = function(api) {
    api.add({
        ".main-nav": {
            background: "#333",
            color: "#000",
            "font-weight": "bold",
            p: {
                "font-size": "20px"
            }
        }
    })
}

You should assign a function to module.exports. It accepts a reference to the API, which has several methods, but the most important one is add. Simply pass a JSON object and it will be converted to CSS.

您应该将一个功能分配给module.exports 。 它接受对API的引用,该API有多种方法,但最重要的是add 。 只需传递一个JSON对象,它将被转换为CSS。

To compile the less file we need install LESS's compiler via npm install -g less and run

要编译less文件,我们需要通过npm install -g less安装LESS的编译器并运行

lessc .\css.less > styles.less.css

It's the almost the same with AbsurdJS. Installation is again via node package manager - npm install -g absurd.

AbsurdJS几乎是一样的。 再次通过节点软件包管理器npm install -g absurd

absurd -s css.js -o styles.absurd.css

It accepts source and output; the result is the same.

它接受源和输出; 结果是一样的。

真相 (The Truth)

You may have really beautiful and nice-looking LESS or SASS files, but what matters is the final compiled CSS. Unfortunately the result is not always the best one.

您可能有非常漂亮,漂亮的LESS或SASS文件,但重要的是最终编译CSS。 不幸的是,结果并不总是最好的。

结合 (Combining)

Let's get the following example:

让我们看下面的例子:

.main-nav {
    background: #333;
}
.main-content {
    background: #333;
}

If you pass this to the current preprocessors you will get the same thing in the end. However if you use AbsurdJS like that:

如果将其传递给当前的预处理器,最终将得到相同的结果。 但是,如果您这样使用AbsurdJS:

module.exports = function(api) {
    api.add({
        ".main-nav": {
            background: "#333"
        },
        ".main-content": {
            background: "#333"
        }
    })
}

After the compilation you will get

编译后,您将获得

.main-nav, .main-content {
    background: #333;
}

SASS has a feature called placeholders which does the same thing. However, it comes with its own problems. Placeholders can't accept parameters and you should repeat them in every selector which you want to combine. My solution just parses the rules and combine them. Let's get a little bit more complex example:

SASS具有一个称为占位符的功能,可以执行相同的操作。 但是,它有其自身的问题。 占位符不能接受参数,您应该在要组合的每个选择器中重复它们。 我的解决方案只是解析规则并将它们组合在一起。 让我们来看一些更复杂的示例:

{
    ".main-nav": {
        background: "#333",
        ".logo": {
            color: "#9f0000",
            margin: 0
        }
    },
    ".main-content": {
        background: "#333"
    },
    section: {
        color: "#9f0000",
        ".box": {
            margin: 0
        }
    }
}

The result is

结果是

.main-nav, .main-content {
    background: #333;
}
.main-nav .logo, section {
    color: #9f0000;
}
.main-nav .logo, section .box {
    margin: 0;
}
section .box {
    padding: 10px;
    font-size: 24px;
}

All identical styles are combined into one single definition. I know that the browsers are really fast nowadays and this is not exactly the most important optimization, but it could decrease the file size.

所有相同的样式都组合为一个定义。 我知道当今的浏览器确实非常快,这并不是最重要的优化,但是它可以减小文件大小。

覆写 (Overwriting)

You know that if you have two identical selectors and they contain definition of the same style the second one overwrites the first. The following code passed through LESS/SASS stays the same:

您知道如果您有两个相同的选择器,并且它们包含相同样式的定义,则第二个选择器将覆盖第一个选择器。 通过LESS / SASS传递的以下代码保持不变:

.main-nav {
   font-size: 20px;
}
.main-nav {
   font-size: 30px;
}

However I think that this leaves one more operation for the browser: it has to find out that there is another definition with the same selector and style and compute the correct value. Isn't it better to avoid this, so send that directly:

但是,我认为这会给浏览器留下更多的操作:它必须找出另一个具有相同选择器和样式的定义,然后计算正确的值。 避免这种情况不是更好,所以直接发送:

.main-nav {
    font-size: 30px;
}

AbsurdJS takes care about this and produces only one definition. The input may look like that:

AbsurdJS对此很在意,只产生一个定义。 输入看起来像这样:

{
    ".main-nav": {
        "font-size": "20px"
    },
    ".main-nav": {
        "font-size": "30px"
    }
}

It also makes your debugging processes easier, because there is no so long chain of overwrites.

这也使调试过程更容易,因为没有那么长的覆盖链。

灵活性 (Flexibility)

Ok, we have mixins, variables, placeholders, functions, but once you start using them to write a little bit more complex things you are stuck. Let's get the mixins. I want to create a mixin, which defines another mixin. That's currently not possible in LESS, because you can't use a mixin defined in another mixin. I guess it's a scope problem. SASS has some imperfections regarding the interpolation of the variables. Overall, it's hard to produce good architecture with less code. You have to write a lot and even then, you can't really achieve your goals. The main reason behind these problems is the fact that both, LESS and SASS, have to deal with new syntax, new rules and basically invent a new compiler. However, if we use JavaScript we don't have to think about these issues.

好的,我们有混入,变量,占位符,函数,但是一旦开始使用它们来编写一些更复杂的东西,就会遇到麻烦。 让我们获取mixins。 我想创建一个mixin,它定义了另一个mixin。 目前在LESS中是不可能的,因为您不能使用在另一个mixin中定义的mixin。 我想这是一个范围问题。 SASS在变量插值方面有一些缺陷 。 总体而言,很难用更少的代码来生成好的架构。 您必须写很多东西,即使那样,您也无法真正实现目标。 这些问题背后的主要原因是,LESS和SASS都必须处理新的语法,新的规则并从根本上发明新的编译器。 但是,如果我们使用JavaScript,则不必考虑这些问题。

AbsurdJS has something called storage. It could save whatever you want and make it available in other files. For example:

AbsurdJS有一个称为storage的东西。 它可以保存您想要的任何内容,并使其在其他文件中可用。 例如:

// B.js
module.exports = function(api) {
    api.storage("theme", function(type) {
        switch(type) {
            case "dark": return { color: "#333", "font-size": "20px" }; break;
            case "light": return { color: "#FFF", "font-size": "22px" }; break;
            default: return { color: "#999", "font-size": "18px" };
        }
    });
}

// A.js
module.exports = function(api) {
    api
    .import(__dirname + "/B.js")
    .add({
        ".main-nav": [
            {
                "font-size": "16px",
                padding: 0,
                margin: 0
            },
            api.storage("theme")("dark")
        ]
    });
}

At the end you get:

最后,您将获得:

.main-nav {
    color: #333;
    font-size: 20px;
    padding: 0;
    margin: 0;
}

Using the storage may be a little bit ugly. I mean, you need an array assigned to the selector and then call api.storage. I used that for a while, but later decided to implement something much nicer. It's a feature which I always wanted - the ability to create your own properties and save tons lines. For example, let's create a new property called theme and process its value.

使用存储可能有点麻烦。 我的意思是,您需要将一个数组分配给选择器,然后调用api.storage 。 我使用了一段时间,但后来决定实现更好的东西。 这是我一直想要的功能-能够创建自己的属性并保存吨线。 例如,让我们创建一个称为theme的新属性并处理其值。

// B.js - definition of the plugin 
module.exports = function(api) {
    api.plugin('theme', function(api, type) {
        switch(type) {
            case "dark": return { color: "#333", "font-size": "20px" }; break;
            case "light": return { color: "#FFF", "font-size": "22px" }; break;
            default: return { color: "#999", "font-size": "18px" };
        }
    });
}

// A.js - its usage
module.exports = function(api) {
    api
    .import(__dirname + "/B.js")
    .add({
        ".header": {
            theme: "light"
        }
    })
}

Again, the result is similar:

同样,结果类似:

.header {
    color: #FFF;
    font-size: 22px;
}


结论 (Conclusion)

AbsurdJS is something really simple, but avoids the usage of popular CSS preprocessors. It still has the same feature like nested selectors, media queries bubbling, file import, variables, mixins and so one. However, it brings more flexibility, because it is a pure JavaScript. It has even a GruntJS support. I'd like to get some feedback and will be happy if you take a part in the project. The official repository is available here https://github.com/krasimir/absurd.

AbsurdJS确实很简单,但是避免了使用流行CSS预处理器。 它仍然具有与嵌套选择器,媒体查询冒泡,文件导入,变量,mixins等相同的功能。 但是,它带来了更大的灵活性,因为它是纯JavaScript。 它甚至具有GruntJS支持 。 我想获得一些反馈,如果您参与该项目,将很高兴。 官方存储库位于https://github.com/krasimir/absurd

翻译自: https://davidwalsh.name/write-css-javascript

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值