DEV Community

Alexander Alemayhu
Alexander Alemayhu

Posted on

CSS in Imba - Inlined Syntax

In this post, I want to go into the language support Imba has for CSS. I am not talking about using <link href="..." rel="stylesheet">, but writing the CSS code within the same file of the element you are styling.

What is Imba?

Quickly before diving into the CSS, let me tell you a little bit about Imba 😊

Imba is a programming language for writing powerful web apps. It compiles down to JavaScript. The name comes from the gaming term imbalance. The interactive learning platform Scrimba is a heavy user of Imba. If you want to learn about the language, check out the official documentation at imba.io. It's all work in progress so feel free to report any issues you see or lack of things at the imba.io repository.

GitHub logo imba / imba.io

📄The official website of Imba

Imba's official website and documentation.

Contributing

Contributions are highly appreciated. The easiest way to contribute to the documentation is by editing /content/docs/undocumented.md.

This includes:

  • Polishing any of the undocumented examples or creating your own examples.

  • Moving examples from undocumented to a relevant location on the documentation.

  • Coming up with proper names for undocumented features with ambiguous names.

For big changes it's best to ask first. You can reach out to us on Discord or create an issue here on Github. We don't bite!

Installation

Fork the repository, then:

git clone https://github.com/your-fork/imba.io
cd imba.io
npm i
npm run dev
Enter fullscreen mode Exit fullscreen mode

Contributing Guide

Adding Documentation

You can find the main documentation in /content/docs/.

See our proprietary markdown syntax guide below.

Adding API Reference Examples

To add your own example, add it to /content/examples/api/.

The API docs are unique in that they are automatically included as examples for any…

Inline Styles Properties on Tags

Before the 1.5.0 release, Imba already had syntax for writing CSS. Let's take a look at a line from the private Scrimba codebase (I have permission to use this ;)

    var embed = <div css:position="relative" css:paddingBottom="{9/16*100}%">

    # Compiled output below
    var _t1, Imba = require('imba'), _1 = Imba.createElementFactory(/*SCOPEID*/);
    var embed = (_1('div').css('position',"relative")).css('paddingBottom',("" + (9 / 16 * 100) + "%")).end();
Enter fullscreen mode Exit fullscreen mode

In the above snippet, we set the position and padding-bottom on the div element. The lines can get pretty long since it's inlined into the tag. One thing that some Imba programmers do is break it up into multiline:

    var embed = <div 
                css:position="relative" 
                css:paddingBottom="{9/16*100}%">
Enter fullscreen mode Exit fullscreen mode

But is that more readable? What if you want to set 7 - 23 different properties? This gets ugly fast. What is the solution to this? Enter SFC!

Single File Components

In Imba 1.5 experimental multi-line syntax for writing CSS landed. This is how it looks like:

    tag embed
        ### css
        .embed {
            position: relative;
            padding-bottom: 40px 
        }
        ###

    # Compiled output below 
    var styles = document.createElement('style');
    styles.textContent = ".embed{position:relative;padding-bottom:40px;}\n";
    document.head.appendChild(styles);
    var Imba = require('imba'), _1 = Imba.createTagScope("fcedc580");
    _1.defineTag('embed', function(tag){
        /* css
            .embed {
                position: relative;
                padding-bottom: 40px 
            }
            */

    });
Enter fullscreen mode Exit fullscreen mode

This enables us to create single file components and makes it so much easier to design interfaces one component at a time 😍

Optionally Scoped

Similar to Vue.js, the syntax also supports scoping the style to the specific component.

    tag embed
        ### css scoped
        .embed {
            position: relative;
            padding-bottom: 40px 
        }
        ###

    # Compiled output below
    var styles = document.createElement('style');
    styles.textContent = ".embed._fcedc580{position:relative;padding-bottom:40px;}\n";
    document.head.appendChild(styles);
    var Imba = require('imba'), _1 = Imba.createTagScope("fcedc580");
    _1.defineTag('embed', function(tag){
        /* css scoped
            .embed {
                position: relative;
                padding-bottom: 40px 
            }
            */

    });
Enter fullscreen mode Exit fullscreen mode

By using css scoped instead of css in the comment a class suffix is added. In the above example, ._fcedc580 is appended to the class name .embed.
What scoped means in simple terms is that only the elements of that tag type will be affected by the defined style.

Using scoped becomes very beneficial when you have lots of tags and files with various styles and would like to select specific things without affecting others. It might not make sense on a landing page but can pay off nicely when you have lots of different layouts and components.

Implementation - How is Imba doing it?

The syntax is heavily inspired by the way Vue.js does it in vue-loader and Vue SFC. Even the initial prototype used the @vue/component-compiler-utils package. While useful, unfortunately, that package has a lot of dependencies that would add too much overhead to the Imba language.

Fortunately, @sombee managed to replace the feature-set by using projects that could be added directly to the vendor directory. This keeps Imba at 0 dependencies 😊

GitHub logo mdevils / css-selector-parser

Just a CSS selector parser.

css-selector-parser

Important:

Latest releases: Changelog.

Installation

npm install css-selector-parser

Usage

Parsing

import {createParser} from 'css-selector-parser';

const parse = createParser();
const selector = parse('a[href^="/"], .container:has(nav) > a[href]:nth-child(2)::before');

console.log(selector);
Enter fullscreen mode Exit fullscreen mode

Produces:

({
    type: 'Selector',
    rules: [
        {
            type: 'Rule',
            items: [
                { type: 'TagName', name: 'a' }
Enter fullscreen mode Exit fullscreen mode

GitHub logo thysultan / stylis

light – weight css preprocessor

STYLIS

stylis

A Light–weight CSS Preprocessor.

Coverage Size Licence NPM

Installation

  • Use a Direct Download: <script src=stylis.js></script>
  • Use a CDN: <script src=unpkg.com/stylis></script>
  • Use NPM: npm install stylis --save

Features

  • nesting a { &:hover {} }
  • selector namespacing
  • vendor prefixing (flex-box, etc...)
  • minification
  • esm module compatible
  • tree-shaking-able

Abstract Syntax Structure

const declaration = {
    value: 'color:red;',
    type: 'decl',
    props: 'color',
    children: 'red',
    line: 1, column: 1
}
const comment = {
    value: '/*@noflip*/',
    type: 'comm',
    props: '/',
    children: '@noflip',
    line: 1, column: 1
}

const ruleset = {
    value: 'h1,h2',
    type: 'rule',
    props: ['h1', 'h2'],
    children: [/* ... */],
    line: 1, column: 1
}

const atruleset = {
    value: '@media (max-width:100), (min-width:100)',
    type: '@media',
Enter fullscreen mode Exit fullscreen mode

Both of these projects were picked due to their small footprint.

Imba Changelog

If you would like to learn about this interactively from a Cast, check out this screencast I did with @somebee on Scrimba

https://scrimba.com/p/pdq9quP/c7P26Ehg

Heads Up

The syntax is still considered experimental so its possible things will change but hopefully not too much. Some other temporary limitations in the compiler are

  • Not being able to handle values like ! and ' which are not encoded / decoded properly #243
  • Also /* [...] */ css comments cause compile errors #242

Those errors have been resolved and the related pull requests need to be merged as of this writing.

Summary

Writing CSS in Imba just got a whole lot easier and even maintaining it now is easier. If you would like to get started with Imba, I have created a boilerplate project based on the hello-world-imba template.

GitHub logo imba / hello-world-imba-sfc

Barebones Imba example using SFC

Hello World Imba SFC

Tiny template for testing out Imba SFC. The project is based on the hello-world-imba template.

This example uses vanilla CSS to show scoped and global examples which was introduced in Imba v1.5.1.

Getting started

git clone https://github.com/imba/hello-world-imba-sfc
cd hello-world-imba-sfc
yarn # npm install

You can run the app in two ways, either served via the webpack-dev-server or Express.

Webpack

# start webpack-dev-server and compiler
yarn run dev # npm run dev
Enter fullscreen mode Exit fullscreen mode

Server side

./node_modules/.bin/imba src/server.imba



If you find the boilerplate useful, please star it ⭐️ GitHub stars are appreciated also to our main repository 🙏🏾

GitHub logo imba / imba

🐤 The friendly full-stack language

Imba

Imba is a friendly full-stack programming language for the web that compiles to performant JavaScript. It has language-level support for defining, extending, subclassing, instantiating and rendering DOM nodes.

Get started

Try Imba instantly in your browser with our playground, or create a new project with:

npx imba create
Enter fullscreen mode Exit fullscreen mode

Documentation

To get started with Imba, we recommend reading through the official guide.

Why Imba?

Minimal syntax

Imba's syntax is minimal, beautiful, and packed with clever features. It combines logic, markup and styling in a powerful way. Fewer keystrokes and less switching files mean you'll be able to build things fast.

import './util/reset.css'
global css html,body m:0 p:0 w:100% h:100%

tag login-form < form

    css input rd:md bc:gray3 h:20px fs:md
    css button rd:md c:white
Enter fullscreen mode Exit fullscreen mode

If you would like to keep up with the Imba development attend our Bi-Weekly Community meetings via zoom. For the next date see the last meeting notes.

Thank you for reading.

Top comments (2)

Collapse
 
itachiuchiha profile image
Itachi Uchiha

Thanks, Alexander. I loved this :)

Is there a pythonic way mm like imba.

Collapse
 
alexanderalemayhu profile image
Alexander Alemayhu • Edited

I am still new to writing here so hopefully, the quality will improve over time, but glad you like it :D

Ahem... I don't really know Python web stuff that much other than Django, Brython and some other random projects. Unfortunately, I don't know of any projects similar to Imba in the Python ecosystem.

Thanks.