Positionnement par ancre CSS interactif
Positionnement par ancre CSS interactif
HTML
index.html <form class="controls">
<fieldset>
<legend>Inline</legend>
<label>
<input type="radio" name="position-inline" value="left" checked />
Left
</label>
<label>
<input type="radio" name="position-inline" value="center" />
Center
</label>
<label>
<input type="radio" name="position-inline" value="right" />
Right
</label>
</fieldset>
<fieldset>
<legend>Block</legend>
<label>
<input type="radio" name="position-block" value="top" checked />
Top
</label>
<label>
<input type="radio" name="position-block" value="center" />
Center
</label>
<label>
<input type="radio" name="position-block" value="bottom" />
Bottom
</label>
</fieldset>
</form>
<div>
<button class="open anchor" type="button">Anchor</button>
<article class="anchor-positioned top-left" style="--position-inline: right; --position-block: bottom;">
top-left*
</article>
<article class="anchor-positioned top-right" style="--position-inline: left; --position-block: bottom;">
top-right*
</article>
<article class="anchor-positioned bottom-right" style="--position-inline: left; --position-block: top;">
bottom-right*
</article>
<article class="anchor-positioned bottom-left" style="--position-inline: right; --position-block: top;">
bottom-left*
</article>
</div>
<p class="note">* Position du point d’ancrage</p>
CSS
style.css @layer demo {
.anchor {
anchor-name: --myAnchor;
}
.anchor-positioned {
position: absolute;
position-anchor: --myAnchor;
&.top-left {
top: anchor(var(--position-block));
left: anchor(var(--position-inline));
}
&.top-right {
top: anchor(var(--position-block));
right: anchor(var(--position-inline));
}
&.bottom-right {
bottom: anchor(var(--position-block));
right: anchor(var(--position-inline));
}
&.bottom-left {
bottom: anchor(var(--position-block));
left: anchor(var(--position-inline));
}
}
}
@layer demoStyles {
body {
flex-direction: column;
}
.open {
width: 300px;
height: 300px;
padding: 1rem;
background: orange;
border: 1px dashed white;
}
.anchor-positioned {
position: relative;
width: fit-content;
padding: 1rem;
background-color: rgb(0 255 255 / 80%);
border: 1px dashed white;
&::after {
content: '';
position: absolute;
width: 6px;
height: 6px;
background-color: red;
border-radius: 100vmax;
}
&.top-left::after {
top: 0;
left: 0;
transform: translate(-50%, -50%);
}
&.top-right::after {
top: 0;
right: 0;
transform: translate(50%, -50%);
}
&.bottom-right::after {
right: 0;
bottom: 0;
transform: translate(50%, 50%);
}
&.bottom-left::after {
bottom: 0;
left: 0;
transform: translate(-50%, 50%);
}
}
.controls {
position: absolute;
top: 0;
right: 0;
display: grid;
gap: 1rem;
padding: 1rem;
background-color: white;
fieldset {
display: grid;
gap: 0.25rem;
border: 0;
}
legend {
font-weight: 700;
}
}
.note {
color: red;
}
}
JavaScript
script.js const controls = document.querySelector('.controls');
const anchorsPositioned = document.querySelectorAll('.anchor-positioned');
controls.addEventListener('change', () => {
const inline = controls.querySelector('[name="position-inline"]:checked').value;
const block = controls.querySelector('[name="position-block"]:checked').value;
anchorsPositioned.forEach(anchorPositioned => {
anchorPositioned.style.setProperty('--position-inline', inline);
anchorPositioned.style.setProperty('--position-block', block);
});
});