Flutter styling explained in CSS - LLF #5

Keff - Oct 1 '21 - - Dev Community

Hey there 👋

CSS can be weird and confusing, so let me explain Flutter's styling using it as a comparison. Flutter styling is quite straightforward, and that's not acceptable in my book, styling should always be confusing and weird.


Jokes aside, CSS is widely used so I thought I'd try to explain Flutter's styling using CSS as a comparison example.

They have a lot of things in common in terms of naming, property (style) values, and the rendered output you'd expect. But as opposed to the web, in Flutter you write styles in the same language as the rest of your application, without needing a separate one for the styles. In the case of Flutter, we write the styles in the Dart language itself.

Let's take a look at some of the most common styles we will use while building Flutter apps.

There is a repository containing an app with all the flutter code mentioned in this post. Can be found here

Table of Contents

Layout

Let's start with layouts. In both flutter and CSS, we can position and organize elements/widgets as we please. Maybe we need to have some items in a row or a column. Or maybe we want to make a scrollable list.

Let's take a look at some of the more common layouts we will use:

Column

Position a list of elements in a vertical orientation (or column).

CSS

<div class="column">
    <div class="item">...</div>
    <div class="item">...</div>
    ...
</div>
Enter fullscreen mode Exit fullscreen mode

In CSS the above will automatically place the items in a column. But to better resemble Flutter, let's take an example of how to do this using flex-box:

<style>
    .column {
        display: flex;
        flex-direction: column;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter

build(context) {
    return Column(
        children: [
            Item(),
            Item(),
        ],
    );
}
Enter fullscreen mode Exit fullscreen mode

As you can see Flutter takes a more composable approach, preferring widgets over properties.

Row

To position items in a row, it's the same drill.

CSS

<style>
    .row {
        display: flex;
        flex-direction: row;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

In CSS we just need to change the flex-direction to row, this will place all items horizontally side by side.

Flutter

build(context) {
    return Row(
        children: [
            Item(),
            Item(),
        ],
    );
}
Enter fullscreen mode Exit fullscreen mode

And in Flutter we can switch the Column widget with Row and we're sorted!

Column and Row are just Flex

With some properties set by default, and some forced (like direction). We could use Flex instead of Row or Column, in the following example it will render the same thing as using Column:

build(context) {
    return Flex(
        direction: Axis.vertical,
        children: [
            Item(),
            Item(),
        ],
    );
}
Enter fullscreen mode Exit fullscreen mode

Center

Yall like centering stuff right? I do, and flutter makes it quite easy to do so. Let's say we want to position an icon in the center of a box.

CSS
In css there are plenty of different ways to do any single thing, we could use our old friend flex-box:

<div class="box">
    <span class="icon">...</span>
</div>

<style>
    .box {
        width: 30px;
        height: 30px;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Or, we could use absolute positioning:


<style>
.container {
  height: 200px;
  position: relative;
  border: 3px solid green;
}

.center {
  margin: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}
</style>

<div class="container">
  <div class="center">
    <button>Centered Button</button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Flutter
Like in CSS in flutter we can center stuff on the screen in multiple ways

Using the Center widget, if we only have a child:

build(context) {
    return Center(
        child: Item()
    );
}
Enter fullscreen mode Exit fullscreen mode

Or we could center things inside a Column or Row if we have more than one element:

build(context) {
    return Row(
        mainAxisAligment: MainAxisAlignment.center,
        crossAxisAligment: CrossAxisAlignment.center,
        children: [
            Item(),
            Item(),
        ],
    );
}
Enter fullscreen mode Exit fullscreen mode

This will center all items centered, both horizontally and vertically.

Note that using this approach we can position items in various ways, like spaceBetween, spaceEvenly, etc...

Stack

What if we want to position an element on top of another element, or positioned on the top right corner? That's absolutely possible

CSS
In css we would use absolute positioning

<div class="parent">
    <span class="child">...</span>
</div>

<style>
    .parent {
        width: 30px;
        height: 30px;
        position: relative; <!-- This is required -->
    }

    .child {
        position: absolute;
        top: 15px;
        right: 15px;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
In flutter we accomplish this by using the Stack widget:

Stack(
  children: [
    Container(
        width: 100,
        height: 100,
    ),

    // This will be rendered on top of previous widgets
    Positioned(
        top: 15, 
        right: 15,
        child: Icon(Icons.close),
    ),
  ],
);
Enter fullscreen mode Exit fullscreen mode

Stack: A widget that positions its children relative to the edges of its box.

Image if how CSS renders

This is how it looks in CSS


Text

One of the most important things of any UI is the text, without text, our apps and websites would just be a bunch of boxes and imagery. Let's see how text is added and handled.

Paragraph

CSS
In css we normally use the <p> tag:

<p>
    CSS stands for Complicated Sac of Sheets
</p>
Enter fullscreen mode Exit fullscreen mode

What about adding some color? Easy

<p class="red">
    CSS stands for Complicated Sac of Sheets
</p>

<style>
    .red {
        color: red;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
Flutter also offers a simple widget to help us render text, called Text:

Text('Flutter is a type of arrhythmia');
Enter fullscreen mode Exit fullscreen mode

And coloring it is simple enough too:

Text(
    'Flutter is a type of arrhythmia',
    style: TextStyle(color: Colors.red),
);
Enter fullscreen mode Exit fullscreen mode

Multiple styles in a paragraph

CSS
In css we can nest <span> elements inside our <p> and give specific styles to each one of them:

<p>
    CSS stands for <span class="css-description">Complicated Sac of Sheets</span>
</p>

<style>
    p {
        color: #666666;
        font-size: 14px;
    }

    .css-description {
        color: brown;
        font-size: 20px;
    }

</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
In flutter we must use the RichText widget to be able to do this, let's take a look:

RichText(
    text: TextSpan(
        children: [
            TextSpan(
                text: 'Flutter is',
                style: TextStyle(
                    color: Color(0xff666666),
                    fontSize: 14,
                ),
            ),
            TextSpan(
                text: 'a type of arrhythmia',
                style: TextStyle(
                    color: Colors.brown,
                    fontSize: 20,
                ),
            )
        ],
    ),
);
Enter fullscreen mode Exit fullscreen mode

As you can see in flutter it's a bit more cumbersome as opposed to CSS.

Image of how the text from the examples looks like

This is how the text mentioned in the example looks like in CSS


Images

CSS
Showing images in CSS is easy enough, just add a <img> tag and set the src attribute to the image path or link.

<img src="http://example.images.com/my-image.png">
Enter fullscreen mode Exit fullscreen mode

Flutter
In Flutter it's quite similar, but we create images differently depending on where the image is loaded from.

Network images

Image.network('http://example.images.com/my-image.png');
Enter fullscreen mode Exit fullscreen mode

see more

Asset images

Image.asset('assets/my-image.png');
Enter fullscreen mode Exit fullscreen mode

see more

In memory images:

Image.memory(bytes);
Enter fullscreen mode Exit fullscreen mode

see more

File images:

Image.file(file);
Enter fullscreen mode Exit fullscreen mode

see more

Bonus meme


Box decorations

We all like those boxes with rounded corners, borders, and excessive gradients, right?

Borders

In CSS we set the border property

<div class="parent"></div>

<style>
    .parent {
        width: 150px;
        height: 150px;
        border: 2px solid green;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
In Flutter we can add borders to a container by setting the border in the containers BoxDecoration:

Container(
    decoration: BoxDecoration(
        border: Border.all(
            color: Colors.green, 
            width: 2,
        ),
    ),
    child: ...
)
Enter fullscreen mode Exit fullscreen mode

Border radius

CSS
In css we use the border-radius property

<div class="parent"></div>

<style>
    .parent {
        width: 150px;
        height: 150px;
        border-radius: 10px;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
In Flutter we can add rounded corners to a container adding BorderRadius to the containers BoxDecoration:

Container(
    decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(10),
    ),
    child: ...
)
Enter fullscreen mode Exit fullscreen mode

Or just adding radius to the top of the container:

Container(
    decoration: BoxDecoration(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(10),
            topRight: Radius.circular(10),
        ),
    ),
    child: ...
)
Enter fullscreen mode Exit fullscreen mode

Want to add rounded corners to any widget? Using ClipRRect allows us to add round corners to any child widget:

ClipRRect(
    borderRadius: BorderRadius.circular(10),
    child: Image.network(
        '...',
        height: 150.0,
        width: 100.0,
    ),
)
Enter fullscreen mode Exit fullscreen mode

Gradients

CSS
In CSS we can set a gradient as the background of elements:

<div class="parent"></div>

<style>
    .parent {
        width: 150px;
        height: 150px;
        background: linear-gradient(70deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%);
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Flutter
In Flutter we can add also add LinearGradient to the containers BoxDecoration:

Container(
    decoration: BoxDecoration(
        gradient: LinearGradient(
            colors: [
                Colors.yellow, 
                Colors.red,
            ],
            stops: [0, 1] 
        ),
    ),
    child: ...
)
Enter fullscreen mode Exit fullscreen mode

Learning more


That's it for this one, I hope you got something out of it and it did not confuse you more than it helped 😅

These are just some of the styles I could compare, so I might convert this into a mini-series if people are interested.

As always, thanks for reading. And remember to comment if you have any suggestions, doubts, or something you would like me to cover in these posts.


If you're interested in reading more, the next post in the series is similar to this but for JS/React devs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .