Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Web and App implementation guide for Card-Based Design. Trigger when user wants information cards, Pinterest-style layouts, and bite-sized content containers.
.claude/skills/lingxling-card-based-design/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-22 | ✓→✓ | = Same ✓ | 86% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 87% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 60% | 0% |
> "Bite-sized consumption. Encapsulating discrete pieces of information into distinct visual containers."
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.
border-radius: 8px and a medium drop shadow.auto-fit or a Masonry layout.cssbody { background-color: #f0f2f5; /* Standard app background */ padding: 40px; } .card-grid { display: grid; /* Auto-responsive magic */ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 24px; } .card { background: #ffffff; border-radius: 12px; overflow: hidden; /* Keep images inside the rounded corners */ box-shadow: 0 4px 12px rgba(0,0,0,0.08); transition: transform 0.2s, box-shadow 0.2s; display: flex; flex-direction: column; } .card:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.12); } .card-image { width: 100%; height: 200px; object-fit: cover; border-bottom: 1px solid #eee; } .card-content { padding: 20px; flex-grow: 1; /* Pushes footer to the bottom */ } .card-footer { padding: 16px 20px; border-top: 1px solid #eee; display: flex; justify-content: space-between; }
swiftstruct ContentCard: View { var body: some View { VStack(alignment: .leading, spacing: 0) { // Image Area Rectangle() .fill(Color.gray.opacity(0.2)) .frame(height: 160) // Content Area VStack(alignment: .leading, spacing: 8) { Text("Card Title") .font(.headline) Text("A brief description of the content inside this discrete card container.") .font(.subheadline) .foregroundColor(.secondary) .lineLimit(2) } .padding(16) } .background(Color.white) .cornerRadius(12) // Clean, subtle drop shadow .shadow(color: Color.black.opacity(0.08), radius: 12, x: 0, y: 4) } } // In your view: // LazyVGrid(columns: [GridItem(.adaptive(minimum: 160), spacing: 16)]) { ... }
VStack inside a background with .cornerRadius and .shadow is the standard.LazyVGrid with .adaptive(minimum: 160) to automatically create a multi-column card grid that flows perfectly on iPad or iPhone.dartclass ContentCard extends StatelessWidget { @override Widget build(BuildContext context) { return Card( elevation: 4, // Handles shadow natively shadowColor: Colors.black.withOpacity(0.4), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), clipBehavior: Clip.antiAlias, // Critical: stops images from bleeding over corners child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ // Image Area Container( height: 160, color: Colors.grey[300], width: double.infinity, ), // Content Area Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: const [ Text('Card Title', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)), SizedBox(height: 8), Text( 'A brief description of the content inside this discrete card container.', style: TextStyle(color: Colors.black54), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ), ), ], ), ); } } // In your view: Use GridView.builder for the layout
Card widget does almost all the heavy lifting.clipBehavior: Clip.antiAlias on the Card, otherwise the top corners of your images will peek outside the border radius.jsxconst ContentCard = () => { return ( <View style={styles.card}> <View style={styles.imageArea} /> <View style={styles.contentArea}> <Text style={styles.title}>Card Title</Text> <Text style={styles.description} numberOfLines={2}> A brief description of the content inside this discrete card container. </Text> </View> </View> ); }; const styles = StyleSheet.create({ card: { backgroundColor: '#FFF', borderRadius: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.08, shadowRadius: 12, elevation: 4, margin: 8, overflow: 'hidden', // Keeps image inside borders }, imageArea: { height: 160, backgroundColor: '#E0E0E0', }, contentArea: { padding: 16, }, title: { fontSize: 18, fontWeight: '600', marginBottom: 8, }, description: { color: '#666', } }); // In your view: <FlatList numColumns={2} data={data} renderItem={...} />
borderRadius and overflow: 'hidden'.elevation: 4 provides the drop shadow on Android, while the shadow* props handle iOS.react-native-masonry-list, as FlatList cannot do varying row heights in columns.kotlin@Composable fun ContentCard() { // ElevatedCard provides the shadow and shape natively ElevatedCard( elevation = CardDefaults.elevatedCardElevation(defaultElevation = 4.dp), shape = RoundedCornerShape(12.dp), colors = CardDefaults.elevatedCardColors(containerColor = Color.White), modifier = Modifier.fillMaxWidth().padding(8.dp) ) { Column { // Image Area Box( modifier = Modifier .fillMaxWidth() .height(160.dp) .background(Color.LightGray) ) // Content Area Column(modifier = Modifier.padding(16.dp)) { Text( text = "Card Title", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold ) Spacer(Modifier.height(8.dp)) Text( text = "A brief description of the content inside this discrete card container.", style = MaterialTheme.typography.bodyMedium, color = Color.Gray, maxLines = 2, overflow = TextOverflow.Ellipsis ) } } } } // In your view: LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 160.dp)) { ... }
ElevatedCard is the perfect Material 3 component for this. It handles clipping and shadows automatically.GridCells.Adaptive(minSize = 160.dp) in a LazyVerticalGrid to achieve an auto-flowing grid identical to CSS Grid auto-fit.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-22 | pass→pass | 15,422 | 11,759 | -24% | 1 | 1 | 0% | 2,267 | 4,224 | +86% | 0 | 0 | — |
case-01 | fail→pass | 36,808 | 55,315 | +50% | 1 | 1 | 0% | 6,446 | 8,176 | +27% | 0 | 0 | — |
case-02 | fail→pass | 17,951 | 18,552 | +3% | 1 | 1 | 0% | 3,751 | 5,333 | +42% | 0 | 0 | — |
case-03 | pass→pass | 18,119 | 23,625 | +30% | 1 | 1 | 0% | 3,207 | 5,997 | +87% | 0 | 0 | — |
case-04 | pass→pass | 25,633 | 20,340 | -21% | 1 | 1 | 0% | 4,156 | 6,643 | +60% | 0 | 0 | — |
case-05 | pass→pass | 15,212 | 13,117 | -14% | 1 | 1 | 0% | 2,327 | 4,783 | +106% | 0 | 0 | — |
case-06 | pass→pass | 15,498 | 12,458 | -20% | 1 | 1 | 0% | 2,404 | 4,629 | +93% | 0 | 0 | — |
case-07 | pass→pass | 25,702 | 16,916 | -34% | 1 | 1 | 0% | 2,297 | 4,645 | +102% | 0 | 0 | — |
case-08 | pass→pass | 13,720 | 7,672 | -44% | 1 | 1 | 0% | 1,877 | 3,508 | +87% | 0 | 0 | — |
case-09 | pass→pass | 13,468 | 12,797 | -5% | 1 | 1 | 0% | 2,343 | 4,397 | +88% | 0 | 0 | — |
case-10 | pass→pass | 16,483 | 11,692 | -29% | 1 | 1 | 0% | 2,496 | 4,504 | +80% | 0 | 0 | — |
case-11 | pass→pass | 7,381 | 5,458 | -26% | 1 | 1 | 0% | 1,355 | 3,037 | +124% | 0 | 0 | — |
case-12 | pass→pass | 7,525 | 4,489 | -40% | 1 | 1 | 0% | 895 | 2,918 | +226% | 0 | 0 | — |
case-13 | pass→pass | 12,507 | 9,993 | -20% | 1 | 1 | 0% | 1,971 | 4,145 | +110% | 0 | 0 | — |
case-14 | pass→pass | 13,069 | 13,874 | +6% | 1 | 1 | 0% | 2,018 | 4,365 | +116% | 0 | 0 | — |
case-15 | pass→pass | 9,589 | 4,365 | -54% | 1 | 1 | 0% | 1,427 | 2,954 | +107% | 0 | 0 | — |
case-16 | pass→pass | 10,495 | 10,348 | -1% | 1 | 1 | 0% | 1,954 | 4,237 | +117% | 0 | 0 | — |
case-17 | pass→pass | 7,938 | 4,259 | -46% | 1 | 1 | 0% | 960 | 2,968 | +209% | 0 | 0 | — |
case-18 | pass→pass | 15,992 | 3,612 | -77% | 1 | 1 | 0% | 2,184 | 2,829 | +30% | 0 | 0 | — |
case-19 | pass→pass | 4,043 | 2,872 | -29% | 1 | 1 | 0% | 731 | 2,744 | +275% | 0 | 0 | — |
case-20 | pass→pass | 15,298 | 11,842 | -23% | 1 | 1 | 0% | 2,074 | 4,027 | +94% | 0 | 0 | — |
case-21 | pass→pass | 16,937 | 12,874 | -24% | 1 | 1 | 0% | 2,323 | 4,127 | +78% | 0 | 0 | — |
case-23 | pass→pass | 7,660 | 4,502 | -41% | 1 | 1 | 0% | 1,128 | 3,057 | +171% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.