Layered Design
"Stacking context. Interfaces built from overlapping, independent layers."
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
- Explicit Overlap: Elements intentionally overlap each other to break the grid and show depth.
- Clear Stratification: Every layer must be visually distinct via shadow, border, or contrasting color.
- Parallax Scrolling: Background layers move slower than foreground layers during interaction/scrolling.
Visual DNA
- Colors: Monochromatic Brown or Sophisticated Neutral. Layering works best when the background is distinct from the floating elements.
- Typography: Often large, overlapping text that spans across image and background layers.
- Spacing: Negative space is required around overlapping elements so they don't feel cluttered.
Web Implementation
- Heavy use of
position: absolute, negative margins, andz-index. - CSS Example:
.layer-container {
position: relative;
padding: 100px;
}
.layer-bg-image {
position: absolute;
top: 0; right: 0;
width: 60%;
height: 400px;
object-fit: cover;
z-index: 1;
}
.layer-text-box {
position: relative;
z-index: 2; /* Sits above the image */
background: white;
padding: 40px;
width: 50%;
margin-top: 200px; /* Pulls it down over the image */
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
/* Optional: border to define edge */
border-left: 4px solid var(--cta-highlight);
}
App Implementation
SwiftUI
struct LayeredDesignView: View {
var body: some View {
ScrollView {
ZStack(alignment: .top) {
// Background Image Layer (Back)
Image("architectural-bg")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 400)
.offset(x: 40, y: 0) // Shifted right
.zIndex(1)
// Content Card Layer (Front)
VStack(alignment: .leading, spacing: 16) {
Text("Stacking Context")
.font(.largeTitle).bold()
Text("This card intentionally overlaps the background image to create depth without relying on a grid.")
.foregroundColor(.secondary)
}
.padding(40)
.background(Color.white)
.shadow(color: Color.black.opacity(0.1), radius: 30, y: 20)
.offset(x: -40, y: 200) // Shifted left and pulled down
.zIndex(2)
}
.padding(.bottom, 200) // Account for the offset
}
}
}
ZStackis the foundation of layered design in SwiftUI.- Use
.offset()to intentionally break the alignment and create overlapping compositions. - Explicitly set
.zIndex()if your offsets might cause unexpected paint orders.
Flutter
class LayeredDesignScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: SizedBox(
height: 600, // Fixed height stack or use constraints
child: Stack(
children: [
// Background Image Layer
Positioned(
top: 0,
right: -40, // Shifted offscreen right
width: MediaQuery.of(context).size.width * 0.8,
height: 400,
child: Image.asset('assets/architectural-bg.jpg', fit: BoxFit.cover),
),
// Content Card Layer
Positioned(
top: 250, // Overlaps the bottom of the image
left: 20, // Overlaps the left of the image
width: MediaQuery.of(context).size.width * 0.7,
child: Container(
padding: const EdgeInsets.all(40),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 30, offset: const Offset(0, 20))
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('Stacking Context', style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold)),
SizedBox(height: 16),
Text('This card intentionally overlaps the background image.', style: TextStyle(color: Colors.grey)),
],
),
),
),
],
),
),
),
);
}
}
- The
Stackwidget withPositionedchildren is required. - You can use negative values in
Positioned(e.g.,right: -40) to bleed layers off the edge of the screen, which is a common trope in layered design.
React Native
const LayeredDesignScreen = () => {
return (
<ScrollView style={{ flex: 1, backgroundColor: '#F8F8F8' }}>
<View style={{ height: 600 }}>
{/* Background Image Layer */}
<Image
source={{ uri: 'https://example.com/architectural-bg.jpg' }}
style={{
position: 'absolute',
top: 0,
right: -40,
width: '80%',
height: 400,
zIndex: 1,
}}
/>
{/* Content Card Layer */}
<View style={{
position: 'absolute',
top: 250,
left: 20,
width: '70%',
backgroundColor: '#FFF',
padding: 40,
zIndex: 2,
// Deep shadow to separate the layers
shadowColor: '#000', shadowOffset: { width: 0, height: 20 },
shadowOpacity: 0.1, shadowRadius: 30, elevation: 15,
}}>
<Text style={{ fontSize: 32, fontWeight: 'bold', marginBottom: 16 }}>Stacking Context</Text>
<Text style={{ color: '#666' }}>This card intentionally overlaps the background image.</Text>
</View>
</View>
</ScrollView>
);
};
- Heavy use of
position: 'absolute'inside a relative container. - Manage
zIndexexplicitly. Note that on Android,elevationalso controls Z-indexing, so the card must have a higherelevationthan the image.
Jetpack Compose
@Composable
fun LayeredDesignScreen() {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
Box(modifier = Modifier.height(600.dp).fillMaxWidth()) {
// Background Image Layer
Image(
painter = painterResource(id = R.drawable.architectural_bg),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.align(Alignment.TopEnd)
.offset(x = 40.dp) // Bleed off right edge
.width(300.dp)
.height(400.dp)
.zIndex(1f)
)
// Content Card Layer
Box(
modifier = Modifier
.align(Alignment.TopStart)
.offset(x = 20.dp, y = 250.dp) // Overlap the image
.width(280.dp)
.zIndex(2f)
.shadow(30.dp)
.background(Color.White)
.padding(40.dp)
) {
Column {
Text("Stacking Context", fontSize = 32.sp, fontWeight = FontWeight.Bold)
Spacer(Modifier.height(16.dp))
Text("This card intentionally overlaps the background image.", color = Color.Gray)
}
}
}
}
}
Boxacts as your stack.- Use
Modifier.align()to set the baseline position, thenModifier.offset()to push it out of grid alignment. Modifier.zIndex()ensures the content card always renders on top of the image.
Do's and Don'ts
- DO: Use contrasting colors or drop shadows where layers intersect so the boundary is clear.
- DON'T: Trap interactive elements (like buttons) underneath other layers where they cannot be clicked.
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.