Design flat UI components with modern minimalist aesthetics
Design-style skill for Flat Design: zero depth, sharp geometry, and high-contrast solid colors with no shadows or gradients.
Maintainer of this project? Claim this page to edit the listing.
13.6.1Add to Favorites
Why it matters
Create clean, minimalist user interface designs following flat design principles-eliminating skeuomorphic elements, using bold colors, simple typography, and two-dimensional illustrations to build modern, accessible UI components and layouts.
Outcomes
What it gets done
Generate flat design UI components with minimal shadows and gradients
Create color palettes using bold, vibrant flat design color schemes
Design two-dimensional icons and illustrations without depth effects
Build responsive layouts with clean typography and generous whitespace
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/ag-flat-design | bash Overview
Flat Design
A design-style skill for Flat Design - zero depth, sharp geometry, high-contrast solid colors, and no shadows or gradients - with matching Web CSS, SwiftUI, and Flutter implementations. Use it for clean utility apps, civic/government tools, or interfaces that want honest, purely 2D clarity over physical depth metaphors.
What it does
Flat Design is a design-style child skill ('digital surfaces should look digital - embrace the 2D plane'), part of the design-it family and not meant to be triggered directly. Three core principles: Zero Depth (absolutely no drop shadows, bevels, gradients, or 3D effects - everything sits on the same z-axis), Sharp & Simple Geometries (perfect circles, sharp rectangles, no complex organic shapes), and High Contrast Solid Colors (stark contrast between solid color blocks delineates space instead of shadow or elevation).
When to use - and when NOT to
Use it when the user's request matches this deliberately unadorned, purely 2D aesthetic - clean utility apps, government or civic tools, or any interface that wants clarity and honesty about being a flat digital surface rather than mimicking physical depth. As a design sub-style, it's selected by the parent design-it skill's routing rather than invoked on its own.
Inputs and outputs
Visual DNA pairs well with Industrial Chic or Modern Editorial palettes, avoiding gradients entirely, with strong highly legible sans-serifs (Roboto, Open Sans) kept medium-to-bold weight, and solid, monochromatic glyph-style icons without intricate detail - icon complexity is deliberately minimized so it reads clearly at any size without relying on gradients or shading to convey form. The web implementation relies entirely on background colors and borders for structure - cards use border-radius: 0 for sharp corners and a solid border instead of box-shadow, and hover states only change opacity or swap a solid color, never lift or add shadow.
.flat-card {
border: 2px solid var(--primary-text);
border-radius: 0;
/* NO box-shadow */
}
.flat-btn:hover { opacity: 0.8; }
Integrations
SwiftUI enforces the same zero-depth discipline explicitly: never use .shadow() or .cornerRadius(), use .overlay(Rectangle().stroke(...)) for visible borders instead of shadows to delineate space, and hover/tap states only change opacity or swap a solid background color rather than lifting the element. Flutter mirrors this with a Container's BoxDecoration explicitly omitting borderRadius and boxShadow, relying purely on a solid border for structure - the same restraint enforced identically across all three platform implementations.
Who it's for
Designers and developers building a clean, honest, purely 2D interface - utility apps, civic/government tools, or any product that wants clarity over skeuomorphic or elevated visual metaphors - and needs the same zero-depth discipline enforced consistently across web and native platforms - the restraint is the point: every shadow or gradient left in place undermines the flatness the style is built around.
Source README
Flat Design
"Digital surfaces should look digital. Embrace the 2D plane."
When to Use
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the design-it skill and is not meant to be triggered directly.
Core Principles
- Zero Depth: Absolutely no drop shadows, bevels, gradients, or 3D effects. Everything sits on the same z-axis.
- Sharp & Simple Geometries: Perfect circles, sharp rectangles. No complex organic shapes.
- High Contrast Solid Colors: Rely on stark contrast between solid blocks of color to delineate space.
Visual DNA
- Colors: Pairs well with Industrial Chic or Modern Editorial. Avoid gradients entirely.
- Typography: Strong, highly legible sans-serifs (e.g.,
Roboto,Open Sans). Keep it medium to bold. - Icons: Solid, monochromatic, glyph-style icons without intricate details.
Web Implementation
- Rely entirely on background colors and borders for structure.
- CSS Example:
.flat-card {
background-color: var(--secondary-base);
border: 2px solid var(--primary-text);
border-radius: 0; /* Sharp corners preferred */
padding: 32px;
/* NO box-shadow */
}
.flat-btn {
background-color: var(--cta-highlight);
color: #fff;
border: none;
padding: 16px 32px;
font-weight: 700;
text-transform: uppercase;
transition: opacity 0.2s;
}
.flat-btn:hover {
opacity: 0.8; /* Only change opacity or solid color on hover, no lifting */
}
App Implementation
SwiftUI
struct FlatCard: View {
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text("Card Title")
.font(.system(size: 18, weight: .bold))
Text("Content without any depth effects.")
.font(.system(size: 15))
.foregroundColor(.secondary)
Button(action: {}) {
Text("ACTION")
.font(.system(size: 14, weight: .bold))
.foregroundColor(.white)
.padding(.horizontal, 24)
.padding(.vertical, 12)
.background(Color.blue)
// No cornerRadius — sharp edges
}
}
.padding(24)
.background(Color(.secondarySystemBackground))
// NO .shadow() — ever
// NO .cornerRadius() — sharp rectangles
.overlay(
Rectangle().stroke(Color.primary.opacity(0.2), lineWidth: 1)
)
}
}
- Never use
.shadow()or.cornerRadius(). Elements are flat rectangles. - Use
.overlay(Rectangle().stroke(...))for visible borders instead of shadows to delineate space. - Hover/tap states should only change
opacityor swap a solid background color.
Flutter
class FlatCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.grey[100],
border: Border.all(color: Colors.black26, width: 1),
// borderRadius: NONE — sharp corners
// boxShadow: NONE — zero depth
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Card Title',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
const Text('Content without any depth effects.',
style: TextStyle(fontSize: 15, color: Colors.black54)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
elevation: 0, // Critical: no shadow
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero, // Sharp corners
),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
),
child: const Text('ACTION',
style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 1)),
),
],
),
);
}
}
- Override
ThemeDataglobally to kill all elevation:ThemeData( cardTheme: const CardTheme(elevation: 0, shape: RoundedRectangleBorder()), appBarTheme: const AppBarTheme(elevation: 0), floatingActionButtonTheme: const FloatingActionButtonThemeData(elevation: 0), ) - Use
ContainerwithBoxDecorationinstead ofCardwidget to avoid default elevation.
React Native
const FlatCard = () => (
<View style={{
padding: 24,
backgroundColor: '#F0F0F0',
borderWidth: 1,
borderColor: '#CCCCCC',
// NO borderRadius
// NO elevation or shadow properties
}}>
<Text style={{ fontSize: 18, fontWeight: '700', marginBottom: 16 }}>
Card Title
</Text>
<Text style={{ fontSize: 15, color: '#666', marginBottom: 16 }}>
Content without any depth effects.
</Text>
<TouchableOpacity
style={{
backgroundColor: '#2196F3',
paddingHorizontal: 24,
paddingVertical: 12,
alignSelf: 'flex-start',
// NO borderRadius, NO elevation
}}
activeOpacity={0.7}
>
<Text style={{ color: '#FFF', fontWeight: '700', letterSpacing: 1 }}>
ACTION
</Text>
</TouchableOpacity>
</View>
);
- Explicitly set
elevation: 0and remove ALL shadow properties (shadowColor,shadowOffset, etc.). - If using React Native Paper, override the theme:
const theme = { ...DefaultTheme, roundness: 0, }. - Tap feedback should change
backgroundColordirectly, not add glow or lift.
Jetpack Compose
@Composable
fun FlatCard() {
Column(
modifier = Modifier
.background(Color(0xFFF0F0F0))
.border(1.dp, Color(0xFFCCCCCC))
.padding(24.dp)
) {
Text("Card Title", fontSize = 18.sp, fontWeight = FontWeight.Bold)
Spacer(Modifier.height(16.dp))
Text("Content without any depth effects.",
fontSize = 15.sp, color = Color(0xFF666666))
Spacer(Modifier.height(16.dp))
Button(
onClick = {},
shape = RectangleShape, // Sharp corners
elevation = ButtonDefaults.buttonElevation(
defaultElevation = 0.dp, // No shadow
pressedElevation = 0.dp,
),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF2196F3)),
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 12.dp),
) {
Text("ACTION", fontWeight = FontWeight.Bold, letterSpacing = 1.sp)
}
}
}
- Override
MaterialThemeshapes:shapes = Shapes(small = RectangleShape, medium = RectangleShape, large = RectangleShape). - Set all elevation to
0.dponCard,TopAppBar, andFloatingActionButton. - Use
Modifier.border()instead of elevation to separate UI regions.
Do's and Don'ts
- DO: Use solid, contrasting borders to separate overlapping elements.
- DON'T: Use any transparency (rgba) or blur effects.
Limitations
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.