Labs ICT
Pro Login

Stateless Widgets

Widgets that don't change over time.

What is a StatelessWidget?

A StatelessWidget is a widget that doesn't change once it's built. Think of it as a snapshot — it displays data but never updates itself. It's the simplest type of widget in Flutter, and you'll use it more than any other.

To create one, extend StatelessWidget and override the build method. The build method returns a widget tree that describes what should appear on screen. You pass data through the constructor and use it in build. That's it — no state, no complexity, just pure display.

import 'package:flutter/material.dart';

class GreetingCard extends StatelessWidget {
  final String name;
  final String message;

  const GreetingCard({
    Key? key,
    required this.name,
    required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Hello, $name!',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 8),
            Text(message),
          ],
        ),
      ),
    );
  }
}
Try it Yourself →

When to Use StatelessWidget

StatelessWidget is perfect for things that are static: a label, an icon, a display card, a divider. If your widget just shows data and doesn't need to react to user interaction or data changes, it should probably be stateless.

// Perfect use cases for StatelessWidget
class UserProfile extends StatelessWidget {
  final String username;
  final String email;

  const UserProfile({required this.username, required this.email});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CircleAvatar(
          radius: 40,
          child: Text(username[0].toUpperCase()),
        ),
        SizedBox(height: 8),
        Text(username, style: TextStyle(fontSize: 18)),
        Text(email, style: TextStyle(color: Colors.grey)),
      ],
    );
  }
}

// A simple divider widget
class SectionDivider extends StatelessWidget {
  final String title;

  const SectionDivider({required this.title});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 16),
      child: Row(
        children: [
          Expanded(child: Divider()),
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 16),
            child: Text(title, style: TextStyle(color: Colors.grey)),
          ),
          Expanded(child: Divider()),
        ],
      ),
    );
  }
}
Try it Yourself →

The Key Insight

Here's the important thing: StatelessWidget is the most common widget type. Most of your UI will be stateless. Keep things simple unless you truly need state. If your widget doesn't need to change after it's built, make it stateless. It's faster, simpler, and easier to test.

// This is stateless — it never changes
class ProductCard extends StatelessWidget {
  final String name;
  final double price;
  final String imageUrl;

  const ProductCard({
    required this.name,
    required this.price,
    required this.imageUrl,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          Image.network(imageUrl, height: 150, fit: BoxFit.cover),
          Padding(
            padding: EdgeInsets.all(12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(name, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                SizedBox(height: 4),
                Text('\$${price.toStringAsFixed(2)}', style: TextStyle(color: Colors.green)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

This ProductCard displays product information. It receives data, shows it, and that's all. If you need a button that changes the product's state, that's where StatefulWidget comes in. But the card itself? Pure StatelessWidget.

Try it Yourself →