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>
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>
Flutter
build(context) {
return Column(
children: [
Item(),
Item(),
],
);
}
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>
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(),
],
);
}
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(),
],
);
}
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>
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>
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()
);
}
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(),
],
);
}
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>
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),
),
],
);
Stack: A widget that positions its children relative to the edges of its box.
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>
What about adding some color? Easy
<p class="red">
CSS stands for Complicated Sac of Sheets
</p>
<style>
.red {
color: red;
}
</style>
Flutter
Flutter also offers a simple widget to help us render text, called Text:
Text('Flutter is a type of arrhythmia');
And coloring it is simple enough too:
Text(
'Flutter is a type of arrhythmia',
style: TextStyle(color: Colors.red),
);
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>
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,
),
)
],
),
);
As you can see in flutter it's a bit more cumbersome as opposed to CSS.
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">
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');
Asset images
Image.asset('assets/my-image.png');
In memory images:
Image.memory(bytes);
File images:
Image.file(file);
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>
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: ...
)
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>
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: ...
)
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: ...
)
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,
),
)
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>
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: ...
)
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