Basic Bento
Grille CSS Grid 4×3 à six cellules asymétriques : scale 1.05 et glow violet au survol, transition à ressort — pur CSS, zéro JavaScript.
Cet effet est gratuit — la catégorie Cartes en contient 41 au total, dont 6 gratuits. Effect.Labs regroupe 811 effets vanilla. Découvrir la catégorie →
Exemples d'usage
Comment ça marche
La mise en page repose sur une grille repeat(4, 1fr) / repeat(3, 1fr) et six cellules délibérément asymétriques : .cell-1 s'étend sur 2 colonnes × 2 lignes via grid-area: span 2 / span 2, .cell-4 à .cell-6 occupent chacune deux colonnes (grid-column: span 2), et .cell-2 / .cell-3 tiennent sur une seule colonne. La cellule principale capte naturellement l'œil sans sortir du flux Grid.
Au survol, chaque cellule reçoit simultanément un transform: scale(1.05), un z-index: 10 pour dépasser ses voisines sans provoquer de reflow de layout, une teinte de bordure rgba(99, 102, 241, 0.5) et un box-shadow à 40 px de diffusion violet. La transition à ressort cubic-bezier(0.175, 0.885, 0.32, 1.275) sur 0,4 s provoque un léger dépassement (overshoot) qui donne l'impression que la cellule saute vers l'utilisateur.
Un pseudo-élément ::before en position: absolute; inset: 0 porte un linear-gradient(135deg, rgba(99,102,241,0.1) 0%, transparent 50%). Son opacity passe de 0 à 1 au survol avec une transition distincte à 0,3 s — le coin supérieur gauche de la cellule s'illumine doucement, ajoutant de la profondeur sans alourdir le rendu.
L'effet est pur CSS : le fichier inclut également sept variantes prêtes à l'emploi — .bento-images, .bento-animated, .bento-interactive, .bento-stats, .bento-reveal, .bento-cardstack et .bento-responsive. Les cellules s'appuient sur quatre variables CSS du design system : --bg-card, --radius-lg, --border et --text-secondary — à définir ou à remplacer en ligne selon le contexte.
Accessibilité
- Pas de prefers-reduced-motion dans le CSS fourni : les transitions scale et glow s'exécutent quel que soit le paramètre OS. Pour les projets qui l'exigent, ajoutez
@media (prefers-reduced-motion: reduce) { .bento-cell { transition: none; } }. - Les
div.bento-cellsont desdivsanstabindex,roleniaria-label: non focusables au clavier, l'effet:hovern'est pas déclenché par Tab ou Entrée. - Le conteneur et la grille ne portent aucun rôle ARIA dans le HTML de base — à ajouter selon la sémantique de l'usage (ex.
role="region"+aria-label). - Le contraste des textes dépend des variables CSS
--text-secondaryet--bg-carddéfinies par le thème — vérifier le ratio WCAG AA (≥ 4,5:1) dans le contexte d'intégration. - Pour rendre les cellules accessibles au clavier (liens, boutons), ajouter
tabindex="0"sur chaque cellule et dupliquer les règles:hoveren:focus-visible.
Compatibilité navigateur
Repose sur CSS Grid (grid-template-columns, grid-area: span) et CSS Custom Properties — supportés nativement depuis Chrome 57 / Firefox 52 / Safari 10.1. Zéro dépendance JavaScript.
Sur IE11 et navigateurs sans CSS Grid, les cellules tombent en display: block et s'empilent verticalement — aucune erreur JS, la page reste lisible.
Le code
Copiez les trois blocs dans votre page. Aucune dépendance.
<div class="bento-container">
<div class="bento-grid bento-basic">
<div class="bento-cell cell-1">Featured</div>
<div class="bento-cell cell-2">A</div>
<div class="bento-cell cell-3">B</div>
<div class="bento-cell cell-4">Wide</div>
<div class="bento-cell cell-5">C</div>
<div class="bento-cell cell-6">D</div>
</div>
</div>
.bento-container {
width: 100%;
max-width: 600px;
aspect-ratio: 4 / 3;
}
.bento-grid {
display: grid;
gap: 12px;
width: 100%;
height: 100%;
}
.bento-cell {
background: var(--bg-card);
border-radius: var(--radius-lg);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 0.85rem;
color: var(--text-secondary);
position: relative;
overflow: hidden;
}
.bento-basic {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.bento-basic .cell-1 {
grid-area: span 2 / span 2;
}
.bento-basic .cell-2 {
grid-column: span 1;
}
.bento-basic .cell-3 {
grid-column: span 1;
}
.bento-basic .cell-4 {
grid-column: span 2;
}
.bento-basic .cell-5 {
grid-column: span 2;
}
.bento-basic .cell-6 {
grid-column: span 2;
}
.bento-basic .bento-cell {
transition: 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.bento-basic .bento-cell:hover {
transform: scale(1.05);
z-index: 10;
border-color: rgba(99, 102, 241, 0.5);
box-shadow: rgba(99, 102, 241, 0.3) 0px 20px 40px;
}
.bento-basic .bento-cell::before {
content: "";
position: absolute;
inset: 0px;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
opacity: 0;
transition: opacity 0.3s;
}
.bento-basic .bento-cell:hover::before {
opacity: 1;
}
.bento-images .cell-1 {
grid-area: span 2 / span 2;
}
.bento-images .cell-2 {
grid-column: span 2;
}
.bento-images .cell-3 {
grid-area: span 2 / span 1;
}
.bento-images .cell-4 {
grid-column: span 1;
}
.bento-images .cell-5 {
grid-column: span 2;
}
.bento-images .cell-6 {
grid-column: span 1;
}
.bento-images .bento-cell {
background-size: cover;
background-position: center center;
cursor: pointer;
}
.bento-images .cell-1 {
background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 100%);
}
.bento-images .cell-2 {
background: linear-gradient(135deg, rgb(240, 147, 251) 0%, rgb(245, 87, 108) 100%);
}
.bento-images .cell-3 {
background: linear-gradient(135deg, rgb(79, 172, 254) 0%, rgb(0, 242, 254) 100%);
}
.bento-images .cell-4 {
background: linear-gradient(135deg, rgb(67, 233, 123) 0%, rgb(56, 249, 215) 100%);
}
.bento-images .cell-5 {
background: linear-gradient(135deg, rgb(250, 112, 154) 0%, rgb(254, 225, 64) 100%);
}
.bento-images .cell-6 {
background: linear-gradient(135deg, rgb(161, 140, 209) 0%, rgb(251, 194, 235) 100%);
}
.bento-images .bento-cell .overlay {
position: absolute;
inset: 0px;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: 0.4s;
}
.bento-images .bento-cell .overlay span {
color: white;
font-weight: 700;
font-size: 1rem;
transform: translateY(20px);
transition: transform 0.4s;
}
.bento-images .bento-cell:hover .overlay {
opacity: 1;
}
.bento-images .bento-cell:hover .overlay span {
transform: translateY(0px);
}
.bento-animated .cell-1 {
grid-area: span 1 / span 2;
}
.bento-animated .cell-2 {
grid-area: span 2 / span 1;
}
.bento-animated .cell-3 {
grid-area: span 2 / span 1;
}
.bento-animated .cell-4 {
grid-column: span 2;
}
.bento-animated .cell-5 {
grid-area: span 1 / span 2;
}
.bento-animated .cell-6 {
grid-area: span 1 / span 2;
}
.bento-animated .bento-cell {
opacity: 0;
transform: translateY(30px) scale(0.9);
animation: 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal forwards running bentoFadeIn;
}
.bento-animated .cell-1 {
animation-delay: 0.1s;
background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
}
.bento-animated .cell-2 {
animation-delay: 0.2s;
background: linear-gradient(135deg, rgb(236, 72, 153) 0%, rgb(244, 63, 94) 100%);
}
.bento-animated .cell-3 {
animation-delay: 0.3s;
background: linear-gradient(135deg, rgb(6, 182, 212) 0%, rgb(59, 130, 246) 100%);
}
.bento-animated .cell-4 {
animation-delay: 0.4s;
background: linear-gradient(135deg, rgb(16, 185, 129) 0%, rgb(5, 150, 105) 100%);
}
.bento-animated .cell-5 {
animation-delay: 0.5s;
background: linear-gradient(135deg, rgb(245, 158, 11) 0%, rgb(239, 68, 68) 100%);
}
.bento-animated .cell-6 {
animation-delay: 0.6s;
background: linear-gradient(135deg, rgb(139, 92, 246) 0%, rgb(217, 70, 239) 100%);
}
.bento-animated .bento-cell span {
color: white;
font-weight: 700;
}
.bento-interactive .bento-cell {
cursor: pointer;
transition: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
background: var(--bg-elevated);
}
.bento-interactive .bento-cell.expanded {
z-index: 100;
background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
box-shadow: rgba(99, 102, 241, 0.4) 0px 25px 50px;
grid-area: span 2 / span 2 !important;
}
.bento-interactive .bento-cell .expand-icon {
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(99, 102, 241, 0.2);
display: flex;
align-items: center;
justify-content: center;
transition: 0.3s;
}
.bento-interactive .bento-cell:hover .expand-icon {
background: rgba(99, 102, 241, 0.4);
transform: scale(1.1);
}
.bento-interactive .bento-cell.expanded .expand-icon {
background: rgba(255, 255, 255, 0.2);
}
.bento-interactive .bento-cell.expanded .cell-content span {
color: white;
}
.bento-stats .cell-1 {
grid-area: span 2 / span 2;
}
.bento-stats .cell-2 {
grid-column: span 2;
}
.bento-stats .cell-3 {
grid-column: span 1;
}
.bento-stats .cell-4 {
grid-column: span 1;
}
.bento-stats .cell-5 {
grid-column: span 2;
}
.bento-stats .cell-6 {
grid-column: span 2;
}
.bento-stats .bento-cell {
flex-direction: column;
gap: 8px;
padding: 16px;
}
.bento-stats .cell-1 .stat-number {
font-size: 3rem;
}
.bento-stats .bento-cell:hover .stat-bar-fill {
width: var(--fill-width, 75%);
}
.bento-reveal .cell-1 {
grid-area: span 2 / span 2;
}
.bento-reveal .cell-2 {
grid-area: span 1 / span 2;
}
.bento-reveal .cell-3 {
grid-column: span 2;
}
.bento-reveal .cell-4 {
grid-area: span 1 / span 2;
}
.bento-reveal .cell-5 {
grid-column: span 2;
}
.bento-reveal .bento-cell {
cursor: pointer;
background: var(--bg-elevated);
}
.bento-reveal .bento-cell:hover .reveal-front {
opacity: 0;
transform: scale(1.2);
}
.bento-reveal .bento-cell:hover .reveal-back {
opacity: 1;
transform: scale(1);
}
.bento-reveal .bento-cell:hover {
border-color: rgba(99, 102, 241, 0.3);
box-shadow: rgba(99, 102, 241, 0.2) 0px 10px 30px;
}
.bento-cardstack .cell-1 {
grid-area: span 2 / span 2;
}
.bento-cardstack .cell-2 {
grid-area: span 2 / span 2;
}
.bento-cardstack .cell-3 {
grid-column: span 2;
}
.bento-cardstack .cell-4 {
grid-column: span 2;
}
.bento-cardstack .bento-cell {
padding: 16px;
background: var(--bg-elevated);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(1) {
transform: translate(-50%, -50%) translateX(-30%) rotate(-10deg);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(2) {
transform: translate(-50%, -50%) translateY(-5px);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(3) {
transform: translate(-50%, -50%) translateX(30%) rotate(10deg);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(1) {
transform: translateY(-10px) rotate(-5deg);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(2) {
transform: translateY(-15px);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(3) {
transform: translateY(-10px) rotate(5deg);
}
.bento-responsive .bento-cell {
transition: 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.bento-responsive .bento-cell span {
color: white;
font-weight: 600;
font-size: 0.7rem;
}
.bento-responsive .bento-cell:hover {
transform: scale(1.05);
z-index: 10;
box-shadow: rgba(0, 0, 0, 0.3) 0px 15px 30px;
}
@keyframes bentoFadeIn {
100% {
opacity: 1;
transform: translateY(0px) scale(1);
}
}
/* Variables du design system du site, dont ce code depend. Sans elles,
l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
Valeurs reprises de css/style.css — a adapter librement. */
.bento-container {
--bg-card: #12121a;
--bg-elevated: #1a1a24;
--border: rgba(255, 255, 255, 0.08);
--radius-lg: 0.75rem;
--text-secondary: #a1a1aa;
}
// Effet CSS pur — pas de JavaScript nécessaire
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| --bg-card | défini par le thème | Fond de chaque cellule — remplacez par #1e1e2e pour un fond sombre uniforme. |
| --border | défini par le thème | Couleur du border 1px solid — rgba(255,255,255,0.08) pour un trait discret sur fond sombre. |
| --radius-lg | défini par le thème | Rayon de bordure des cellules — 12px standard, 20px très arrondi. |
| --text-secondary | défini par le thème | Couleur des labels texte dans les cellules — #94a3b8 pour gris doux sur fond sombre. |
| gap: 12px dans .bento-grid | 12px | Espace entre cellules — 8px pour compact, 20px pour aéré. |
| rgba(99,102,241,…) dans .bento-basic .bento-cell:hover et ::before | #6366f1 | Couleur du glow et de l'overlay — 3 occurrences à remplacer par la couleur brand. |
| transform: scale(1.05) dans .bento-basic .bento-cell:hover | 1.05 | Amplitude du zoom au survol — 1.03 pour discret, 1.08 pour prononcé. |
| transition: 0.4s cubic-bezier(0.175,0.885,0.32,1.275) dans .bento-basic .bento-cell | 0.4s ressort | Durée et courbe — 0.25s ease-out pour un comportement linéaire sans overshoot. |
FAQ
L'effet fonctionne-t-il sans JavaScript ?
Oui, Basic Bento est 100 % CSS — aucune ligne de JavaScript. Copiez le HTML et le CSS, et l'effet est immédiatement opérationnel dans n'importe quel framework (React, Vue, Svelte) ou en HTML vanilla.
Comment changer la couleur du glow violet ?
La couleur #6366f1 apparaît à trois endroits dans le CSS : border-color au survol, box-shadow au survol, et le dégradé du ::before. Remplacez toutes les occurrences de rgba(99,102,241,…) par votre couleur brand pour un thème cohérent.
Peut-on utiliser les autres variantes de grille incluses dans le CSS ?
Oui. Le CSS contient sept variantes prêtes à l'emploi : .bento-images (cellules avec images et overlay), .bento-animated (animation d'entrée fadeIn), .bento-interactive (expansion au clic), .bento-stats (métriques), .bento-reveal, .bento-cardstack et .bento-responsive. Il suffit de remplacer la classe .bento-basic sur la grille — la structure HTML des six cellules reste identique.