Web Application Programming in PicoLisp: Adding CSS
Tags: picolisp, webdev, lisp, functional
Published: 2022-01-20 16:06:10

In the last post, we expanded our "Hello World" example by some tags. However, the page still looks really boring. We need to add some styles.

---------------------------

### CSS

CSS stands for **C**ascading **S**tyle **S**heets. The main idea is that you can define the layout independently from the text content. The style instructions are also called "attributes".

There are two possibilities to define CSS attributes: In a separate file or by directly editing the tags within the HTML text.

---------------------------

### Custom CSS files

PicoLisp comes with a pre-defined css-file that includes some very basic stylings, ``lib.css``. You can find it in the root of the PicoLisp installation folder. 

Let's include it to our previous ``helloworld.l``-file. We just need to edit the first line:

```
(html 0 "Hello" "@lib.css" NIL
    ...
```

As the comparison below shows, there are some changes indeed: For instance, the background color is different, and the font type has also changed.

![csscompare.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632474846291/eDgRZk-mmH.png)

----------------------------

In a typical application, you might not only use one css-file, but several ones. In this case, you can hand over a list of files like this:

```
   (html 0 "Project" '("@lib.css" "my1.css" "my2.css") NIL
```
The CSS files that come later in the list will redefine specifications from the previous ones. To increase readibility, you can also use a global variable to define it:

```
(setq *Css '("@lib.css" "my1.css" "my2.css"))

(html 0 "Project" *Css NIL
    ...
```

----------------------------

### How to use CSS frameworks

This is not a CSS-tutorial, so we will not cover this topic in depth. But you should be aware that **the way a styling is displayed depends on a lot of things**: screen width, browser type, browser version... It can be really frustrating to style your app for hours in your Firefox browser, only to realize that it looks completely wrong on Chrome.

The good news is that there is no need to re-invent the wheel. Talented webdesigners have contributed thousands and thousands of hours to **create frameworks that react responsively and reliably on all kinds of browsers and viewports**. One famous example for this is the [Bootstrap framework](https://getbootstrap.com/). For example, the [grid system](https://getbootstrap.com/docs/5.1/examples/grid/) in Bootstrap is quite powerful and a big help to increase responsiveness. 

The standard installation comes with a lot of JavaScript included, but since we only need styles, we can download the .css-files separately from [here](https://getbootstrap.com/docs/4.4/getting-started/download/). The file size is approx. 200 kB.

----------------------------

### A simple CSS example using Bootstrap

Now let's modify our "helloworld.l"-file with some Bootstrap classes. 

Crash-course (better [check the docs!](https://getbootstrap.com/docs/4.0/utilities/borders/)):
- ``m-3`` is short for "margin", level 3. You can choose between 1 to 5. You can add``x`` to only modify left and right margin, or ``y`` for upper and lower margin. 
- ``row`` defines a row, ``col`` a column.
- ``text-primary, secondary, success`` and so on are predefined colors that can be modified in the css-data
- ``d-flex`` is a flexbox where you can style many things, like floating, position, orientation and so on.

Here is the boostrapped ``helloworld.l`` file after I played around with it a little. I admit it's not a great design, I'm sure you can do better than me :-) [You can find the hosted version here on picolisp.com](http://picolisp.com/blog/src/helloworld-bootstrapped.l).

```
(setq *Css '("@lib.css" "css/bootstrap.css"))

(html 0 "Hello World - CSS Bootstrap" *Css NIL
   (<div> "d-flex flex-column"
      (<h1> "d-flex m-5 justify-content-center" "Hello World!")
      (<h2> "d-flex m-3 justify-content-center" "Playing around with Bootstrap classes.") )
   (<hr>)
   (<p> "text-white bg-dark m-4 d-inline-flex p-1"
      "This is a text block. "
      (<strong> " Still the same text block. ")
      " Still a text block.")
   (<hr>)
   (<h5> "ml-5" "This is the bootstrap grid system:")
   (<div> "row mx-3 bg-secondary"
      (<div> "col border rounded m-1 p-3 text-success bg-white" "This is a div in a div."
      (<ul> "text-dark"
         (<li> NIL "Item 1")
         (<li> NIL "Item 2"
         (<ul> "text-secondary"
            (<li> NIL "2-1")
            (<li> NIL "2-2") ) ) ) )
      (<div> "col border rounded m-1 p-3 text-success bg-white" "This is a second div in a div."
      (<ul> "text-dark"
         (<li> NIL "Item 3")
         (<li> NIL "Item 4"
         (<ul> "text-secondary"
            (<li> NIL "4-1")
            (<li> NIL "4-2")
            (<li> "border rounded m-2 text-danger bg-light" "div in a div in a div") ) ) ) ) )
   (<div> "row mx-3 mt-1 bg-secondary"
      (<div> "col border rounded m-1 p-3 bg-white text-center"
         (<img> "img/Sunflower_from_Silesia.JPG" "Sunflower" NIL 300 300) ) )

  (<div> "d-flex flex-column m-5"
      (<p> NIL "View source code on "
         (<href> "Gitlab" "https://gitlab.com/picolisp-blog/web-applications/-/blob/main/bootstrap-example/helloworld-bootstrapped.l" "_blank") ) ) )
```
Below you can see how it looks like both on desktop and mobile browsers. As you can see, the content collapses automatically to fit the screen. There are also options to handle different behaviour depending on screen size and other parameters.

![mobileview.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633416501981/tRanq5f4z.png)

All files can be downloaded [here](https://gitlab.com/picolisp-blog/web-applications/-/tree/main/bootstrap-example).

Of course Bootstrap has its limits - so in order to add or modify your styling, you can always create an additional custom CSS-file to overwrite or expand the defined classes. For example, if you define the ``<h1>`` tag in a new css file ``custom.css``, your definitions will be executed if ``custom.css`` is the **last** file to be called, like this:

```
(setq *Css '("@lib.css" "css/bootstrap.css" "css/custom.css"))
```

----------------------------

### In-line CSS styling

If you still prefer to to add some classes directly to your HTML, you can do so by adding a ["cons pair"](https://picolisp-blog.hashnode.dev/60-picolisp-functions-you-should-know-6-lists-and-strings).

```
(<div> '(style . "margin: 60px;")
```

or 
```
   (<div> '("myClass" (style . "margin: 60px;") ..)
```

However, I wouldn't recommend to do so as you lose some of your flexibility, especially if you also include a .css-file. It also makes debugging your style much more difficult if the CSS is defined in various sources.

----------------------------

As you might have noticed, we didn't have any interactive components yet, so let's start with this topic in the next post.

----------------------------

### Sources
- https://picolisp.com/wiki/?css  
- https://getbootstrap.com/