Aller au contenu principal
Guillaume Duverger Code & graphisme

Cartes produits CSS popover/anchor API

Votre navigateur ne supporte pas cette démonstration

Si la démonstration ne fonctionne pas, activez la fonctionnalité : #enable-experimental-web-platform-features via le drapeau chrome://flags. Attention : La syntaxe sur les ancres a (encore !) changé. La démonstration ci-dessous a été mise à jour.

  • 4,2 sur 5

    131 évaluations

    5 étoiles 55%
    4 étoiles28%
    3 étoiles5%
    2 étoiles3%
    1 étoile9%

    Voir les commentaires clients

    Lorem ipsum

    Offre Black Friday

    -42 % 239,00€

    Prix récent le plus bas : 411,97€

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem. Pellentesque sollicitudin elit elit, eu eleifend nunc maximus auctor.

    Retournez cet article gratuitement

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem.

    En savoir plus sur les retours gratuits.
    Comment retourner l'article ?
    1. Lorem ipsum dolor
    2. Lorem ipsum dolor
    3. Lorem ipsum dolor

    En stock

  • 4,5 sur 5

    10 666 évaluations

    5 étoiles 72%
    4 étoiles18%
    3 étoiles5%
    2 étoiles2%
    1 étoile3%

    Voir les commentaires clients

    Lorem ipsum

    Offre Black Friday

    -31 % 179,99€

    Prix récent le plus bas : 259,99€

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem. Pellentesque sollicitudin elit elit, eu eleifend nunc maximus auctor.

    Retournez cet article gratuitement

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem.

    En savoir plus sur les retours gratuits.
    Comment retourner l'article ?
    1. Lorem ipsum dolor
    2. Lorem ipsum dolor
    3. Lorem ipsum dolor

    En stock

  • 4,2 sur 5

    322 évaluations

    5 étoiles 56%
    4 étoiles22%
    3 étoiles14%
    2 étoiles2%
    1 étoile6%

    Voir les commentaires clients

    Lorem ipsum

    Offre Black Friday

    -31 % 109,99€

    Prix récent le plus bas : 159,99€

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem. Pellentesque sollicitudin elit elit, eu eleifend nunc maximus auctor.

    Retournez cet article gratuitement

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem.

    En savoir plus sur les retours gratuits.
    Comment retourner l'article ?
    1. Lorem ipsum dolor
    2. Lorem ipsum dolor
    3. Lorem ipsum dolor

    En stock




<div class="demo">

<!--on met les icones dans des elements symbol pour les reutiliser, le code entier se trouve dans le telechargement zip-->
<svg height="0" width="0">
<symbol id=info viewBox="0 0 64 64">
...
</symbol>

<symbol id=fleche-bas viewBox="0 0 24 24">
...
</symbol>

<symbol id=fermer viewBox="0 -0.5 25 25">
...
</symbol>

<symbol id=etoile-vide viewBox="0 0 512 512">
...
</symbol>

<symbol id=etoile viewBox="0 0 512 512">
...
</symbol>

<symbol id=etoile1 viewBox="0 0 512 512">
...
</symbol>
</svg>

<!--debut cartes-->
<ul>
<li tabindex="0">
<img src="img.jpg" alt="">
<div class=contenu-carte>
<button id="anchor-classe" popovertarget="tooltip-etoile">
<span class=classement><span>4.2</span>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile-vide"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fleche-bas"></use></svg>
<span>131 évaluations</span>
</span>
</button>
<div id="tooltip-etoile" class="tooltip-etoile" anchor="anchor-classe" popover>	
<div class=classe-tooltip>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile"></use></svg>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#etoile-vide"></use></svg>	
<span>4,2 sur 5</span>
</div>
<p>131 évaluations</p>
<div class=progress>
<div><span>5 étoiles</span><progress max="100" value="55"></progress><span>55%</span></div>
<div><span>4 étoiles</span><progress max="100" value="28"></progress><span>28%</span></div>
<div><span>3 étoiles</span><progress max="100" value="5"></progress><span>5%</span></div>
<div><span>2 étoiles</span><progress max="100" value="3"></progress><span>3%</span></div>
<div><span>1 étoile</span><progress max="100" value="9"></progress><span>9%</span></div>
</div>
<hr>
<a href="">Voir les commentaires clients
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fleche-bas"></use></svg>
</a>
</div>
<h2>Lorem ipsum</h2>
<span class=black>Offre Black Friday</span>
<p class=prix><span>-42 %</span> 239,00€</p>
<div class=recent>
<span>Prix récent le plus bas : <del>411,97€</del></span>
<button id="ancre-info" popovertarget="info-box">
<svg class=info role="img" aria-hidden="false" height="0" width="0" aria-label="Information sur le prix"><use href="#info"></use></svg>
</button>
</div>
<div id="info-box" class="info-box" popover anchor="ancre-info">	
<button class="ferm" popovertarget="info-box" popovertargetaction="hide" autofocus>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fermer"></use></svg>
</button>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem. Pellentesque sollicitudin elit elit, eu eleifend nunc maximus auctor.</p>
</div>
<button class=retour id="ancre-retour" popovertarget="info-retour">
Retours GRATUITS 
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fleche-bas"></use></svg>
</button>
<div id="info-retour" class="info-retour" popover anchor="ancre-retour">	
<button class="ferm" popovertarget="info-retour" popovertargetaction="hide" autofocus>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fermer"></use></svg>
</button>
<h3>Retournez cet article gratuitement</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse porta viverra ante sit amet molestie. Phasellus vel urna dolor. Sed ac lacinia turpis. Duis et vestibulum odio. Vestibulum tincidunt sapien lacus, ut vehicula metus rutrum nec. Nunc vitae porta dui, non laoreet lorem.</p>
<a href="">En savoir plus sur les retours gratuits.</a>
<details>
<summary>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fleche-bas"></use></svg>
Comment retourner l'article ?
</summary>
<ol>
<li>Lorem ipsum dolor</li>	
<li>Lorem ipsum dolor</li>	
<li>Lorem ipsum dolor</li>	
</ol>	
</details>
</div>
<p class=stock>En stock</p>
<label>Quantité :</label>
<selectlist>	
<button type=selectlist>
<selectedoption></selectedoption>
<svg role="img" aria-hidden="true" height="0" width="0"><use href="#fleche-bas"></use></svg>
</button>
<listbox popover>
<option value="1">1</option>
<option value="2">2</option>
</listbox>
</selectlist>
<div class=action>
<button class="panier">Ajouer au panier</button>  
<button class="achat">Acheter cet article</button>  
</div>
</div>
</li>


<li>...</li>

<li>...</li>


</ul>
</div>






*,
*::before,
*::after {
  box-sizing: border-box;
}
		
body{

margin:0;
font-family:system-ui;
color:oklch(10% 0 0);

}

ul{

list-style-type: none;
padding:unset

}

button,summary{

all:unset;
cursor: pointer
}		


*:focus-visible{

outline:2px solid currentcolor;
outline-offset:2px

}

.demo ul{

display:grid;
grid-template-columns:repeat(auto-fit,clamp(calc(50% - 1rem),(100vw - 50rem)*-1000,100%));
gap:1rem;
color:oklch(10% 0 0);

}	

.demo> ul> li{

background:white;
box-shadow: rgba(0, 0, 0, 0.13) 0px 12.8px 28.8px, rgba(0, 0, 0, 0.11) 0px 0px 9.2px;

}

.demo img{

display:block;
aspect-ratio:9/10;
width:100%;
height:auto;
object-fit:contain

}

.demo a{

text-decoration: none;
color: oklch(0.51 0.09 215.66);

}

.demo a:hover{

color:oklch(0.58 0.16 40.76);
text-decoration: underline

}
	
.contenu-carte{

padding:1rem

}
	
.demo h2{

margin:1rem 0

}	
	
[popover] {

border:none;
inset:auto;
margin:0;
scale:calc(1 - var(--a));
opacity: calc(1 - var(--a));
transform-origin: top center

}
	
:is(.tooltip-etoile,.info-retour,.info-box){
	
background-color:white;
inset-area: top;
position-try-fallbacks: flip-block;
padding: 1rem;
border:1px solid #ddd;
border-radius: 5px;
box-shadow:
0px 0.3px 0.5px rgba(0, 0, 0, 0.014),
0px 0.7px 1.3px rgba(0, 0, 0, 0.02),
0px 1.3px 2.4px rgba(0, 0, 0, 0.025),
0px 2.2px 4.2px rgba(0, 0, 0, 0.03),
0px 4.2px 7.9px rgba(0, 0, 0, 0.036),
0px 10px 19px rgba(0, 0, 0, 0.05);
	}			
		
@starting-style {[popover]{--a: 1;}}
	

selectlist{
	
display: inline-flex;
background-color:white;
font-family: inherit	
	}
	
selectlist button {
	
font-size: clamp(1rem,1vw + .85rem,1.125rem);
padding: 10px;
border-radius: 5px;
border: 1px solid #ddd;	
	
}
	
selectlist button{

display:flex;
align-items: center;
justify-content: space-between;
	
	}

selectlist button svg{
	
height:clamp(1rem,1vw + 1rem,1.25rem);
width:clamp(1rem,1vw + 1rem,1.25rem)
	
}
	
	
selectlist>listbox {
background-color:white;
inset-area: bottom;
position-try-fallbacks: flip-block;
padding:0;
border-radius: 5px;
margin:0;

}

	
option {
	
color:#111;
padding: 10px;
cursor: pointer;
display:flex;
	
	}	

option:not(:first-child) {

border-top: 1px solid #aaa;

}
	
option:is(:hover, :focus) {

background-color: #ddd;

}	
	
option:is(:focus-visible){

outline-offset:-4px

}
	
	
@media (prefers-reduced-motion: no-preference) {
	
[popover] { transition: all .25s; }
	
}

	
:is(.info-box,.info-retour) {

width:100%;
max-width: 320px;
	
}
.info-box{	inset-area:top span-right;}

.info{
	
fill:currentcolor;
stroke:currentcolor;
height:clamp(1rem,1vw + 1rem,1.25rem);
width:clamp(1rem,1vw + 1rem,1.25rem)
	
}
		
.ferm{
	
display:flex;
margin-left:auto;
border:1px solid #ddd
	
	}
	
.ferm svg{

height:clamp(1rem,1vw + 1rem,1.25rem);
width:clamp(1rem,1vw + 1rem,1.25rem)

}	

.black{

padding:.5rem 1rem;
border-radius:.25rem;
background:oklch(54% 0.21 19);
color:white

}

.prix{

margin:1rem 0;
font-size:clamp(1.5rem,1rem + 1vw,2rem)

}

.prix span{

color:oklch(54% 0.21 19);
font-size:clamp(1rem,1rem + 1vw,1.5rem)

}

.recent{

display:flex;
gap:.25rem;
align-items: center;
color:#909090 

}

.classement{

display:flex;
align-items:center;
gap:.25rem;

}

.classement svg{

fill:currentcolor;
height:clamp(1rem,1vw + 1rem,1.25rem);
width:clamp(1rem,1vw + 1rem,1.25rem)

}

.stock{

color:green;
font-size:clamp(1rem,1vw + 1rem,1.5rem);
margin:1rem 0

}
	
.action{

display: grid; 
gap:1rem;
place-content:center;
margin:1rem 0 

}

.action button{

border-width:1px;
border-style: solid;
box-shadow: 0 2px 5px 0 rgba(213,217,217,.5);
border-radius:100px;
padding:.5rem 2rem

}

.panier{

background: #FFD814;
border-color: #dbb700;

}	

.achat{

background: #FFA41C;
border-color: #de7d00;

}
	
:is(listbox,.tooltip-etoile) {

min-inline-size: anchor-size(self-inline);

}
	
.classe-tooltip svg{

height:clamp(1rem,1vw + 1rem,1.25rem);
width:clamp(1rem,1vw + 1rem,1.25rem)

}	
.tooltip-etoile hr{

margin:1rem 0;
border:1px solid #eee

}

.tooltip-etoile a{

display:flex;
justify-content: center;
align-items: center;
color: oklch(0.51 0.09 215.66);
text-decoration: none

}	

.tooltip-etoile a svg{
fill:currentcolor;
height:clamp(1rem,1vw + 1rem,1.125rem);
width:clamp(1rem,1vw + 1rem,1.125rem);
rotate:-90deg

}

.tooltip-etoile p{

margin:1rem 0

}	

.classe-tooltip{
display:flex;
align-items:center;
gap:.5rem}

.progress{

display: grid;
gap:1rem;

}

.progress div{

display:grid;
grid-template-columns:60px 1fr 30px;
align-items:center;
column-gap:.5rem;

}

	
@property --progression {

syntax: "<length>";
initial-value: 0px;
inherits: false;
}
	
progress[value] {

--bg:#eaeaea;
--linear:linear-gradient(#ffac10 0 0) no-repeat 0/var(--progression) 100%, var(--bg);
border-radius:.125rem;
height: 20px;
animation:progress .8s .8s linear forwards;

}
	
progress[value]::-webkit-progress-bar{

background-color:var(--bg);
border-radius:.125rem

}

progress[value]::-webkit-progress-value{

border-radius:.125rem;
background:var(--linear)

}

progress[value]::-moz-progress-bar{

border-radius:.125rem;
background:var(--linear)

}
	
	
@keyframes progress{

to{
--progression:200px

}

}
	
.info-retour{

inset-area:top span-right;

}


.info-retour h3{

margin:.5rem 0;

}

.retour{

color: oklch(0.51 0.09 215.66);
margin:1rem 0;
display:flex;
align-items: center;
gap:.25rem

}
	
summary{

color: oklch(0.51 0.09 215.66);
display:flex;
align-items:center

}
	
summary svg,
.retour svg{

fill:currentcolor;
height:clamp(1rem,1vw + 1rem,1.125rem);
width:clamp(1rem,1vw + 1rem,1.125rem)

}