CSS Anchor Positioning: упрощаем разработку связанных друг с другом элементов

Рома Ахмадуллин

Дром

CSS Anchor Positioning

Упрощаем разработку связанных друг с другом элементов

Рома Ахмадуллин, Дром

Рома Ахмадуллин

Позиционирование

box model

box model

Описывает структуру бокса. Каждый бокс имеет content area и необязательные области:
margin, border, padding.

CSS-спецификация
CSS-спецификация: box model

Что ограничивает размеры бокса?

containing block

Прямоугольник, который формирует основу
для определения размера и позиционирования связанных с ним боксов.

CSS-спецификация
CSS-спецификация: containing block

Разные виды позиционирования

разный containing block

Как можем позиционировать элементы?




.container {
    border: 3px solid blue;
}

.container {
    border: 3px solid blue;
    display: flex;
    gap: 20px;
}

.box {
    width: 100px;
    height: 100px;
}

.yellow {
    background: yellow;
}

.yellow {
    background: yellow;
}

position: static


.yellow {

}

.yellow {
    position: static;
}

.yellow {
    position: static;
    top: 20%;
    left: 20%;
}

position: relative


.yellow {
    position: static;
}

.yellow {
    position: relative;
}

.yellow {
    position: relative;
    top: 20%;
    left: 20%;
}

position: absolute


.yellow {
    position: relative;
    top: 20%;
    left: 20%;
}

.yellow {
    position: absolute;
    top: 20%;
    left: 20%;
}

.yellow {
    position: absolute;
    top: 20%;
    left: 20%;
}

.container {
    position: relative;
}

position: fixed


.yellow {
    position: absolute;
    top: 20%;
    left: 20%;
}

.container {
    position: relative;
}

.yellow {
    position: fixed;
    top: 20%;
    left: 20%;
}

.container {
    position: relative;
}

.yellow {
    position: fixed;
    top: 20%;
    left: 20%;
}

position: sticky


.yellow {
    position: fixed;
    top: 20%;
    left: 20%;
}

.yellow {
    position: sticky;
    top: 20%;
    left: 20%;
}

Что имеем?

Итак

Связанные друг с другом элементы

Как привязать элемент к другому?

#1 способ

            
            <div class="a"></div>

            <div class="b"></div>
            
            
            
            <div class="a"></div>

            <div class="b"></div>
            
            
        
        .a {
            position: absolute;
            top: 100px;
            left: 250px;
        }

        .b {
            position: absolute;
            top: 200px;
            left: 350px;
        }
        
        

Плюсы

Плюсы

Минусы

#2 способ

            
            <div class="a">
                <div class="b"></div>
            </div>
            
            
            
            <div class="a">
                <div class="b"></div>
            </div>
            
            
        
        .a {
            position: relative;
        }

        .b {
            position: absolute;
            top: 50%;
            left: 50%;
        }
        
        

Плюсы

Плюсы

Минусы

#3 способ

            
            <div class="a"></div>

            <div class="b"></div>
            
            
            
            <div class="a"></div>

            <div class="b"></div>
            
            
        
        const aPosition = a.getBoundingClientRect();

        const bTop = aPosition.y + aPosition.height / 2;
        const bLeft = aPosition.x + aPosition.width / 2;

        b.style.top = `${bTop}px`;
        b.style.left = `${bLeft}px`;
        
        

Плюсы

Плюсы

Минусы

А если нужна адаптивность?

🤖 JavaScript

            
            import { 
                computePosition, offset, autoPlacement, autoUpdate 
            } from '@floating-ui/dom';

            const updatePosition = () => {
                computePosition(a, b, {
                    middleware: [
                        offset({ mainAxis: -100, crossAxis: 100 }), 
                        autoPlacement(),
                    ],
                }).then(({x, y}) => {
                    Object.assign(b.style, {
                        top: `${y}px`,
                        left: `${x}px`,
                    });
                });
            };

            autoUpdate(a, b, updatePosition);
            
        

Работает

Но как-то муторно...

Можно ли проще?

💡 CSS Anchor Positioning

CSS Anchor Positioning

Определяет, как элемент может менять свой размер и позиционироваться на странице относительно одного или нескольких якорей.

CSS-спецификация
CSS-спецификация: anchor positioning
CSS-спецификация: anchor positioning

Браузерная поддержка

Chrome
Firefox
Safari
Октябрь 2025

Interop 2025

Web platform tests: Interop 2025 Dashboard
Chrome
Firefox
( ✅ )
Safari
Декабрь 2025

Полифил

CSS Anchor Positioning Polyfill

Давайте разбираться

С чего начать?

anchor-name

anchor-name

Объявляет элемент якорным:
определяет имя, с помощью которого другие элементы могут сослаться на текущий.

CSS-спецификация
CSS-спецификация: anchor name
        
        .anchor {
            anchor-name: --my-anchor;
        }
        
        

position-anchor

position-anchor

Указывает дефолтный якорный элемент, относительно которого будет позиционироваться текущий.

CSS-спецификация
CSS-спецификация: position-anchor
        
        .target {
            position-anchor: --my-anchor;
        }
        
        
        
        .target {
            position: absolute;
            position-anchor: --my-anchor;
        }
        
        
        
        .target {
            position: absolute;
            position-anchor: --my-anchor;
        }
        
        
        
        .target {
            position-anchor: --my-anchor;
        }
        
        

⚙️ Пробуем на практике

        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
            }
        
        

Связать – связали

Как позиционировать?

anchor()

anchor()

Функция, ссылающаяся на параметры позиционирования якорного элемента.
Может быть использована только в inset-свойствах.

CSS-спецификация
CSS-спецификация: anchor()
            
                .target {
                    top: anchor(top);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(center);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(center);
                    top: anchor(bottom);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(center);
                    top: anchor(bottom);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(bottom);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(bottom);
                    top: anchor(left);
                    top: anchor(right);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(bottom);
                    top: anchor(left);
                    top: anchor(right);
                }
            
        
            
                .target {
                    top: anchor(top);
                    top: anchor(bottom);
                    top: anchor(left);
                    top: anchor(right);
                }
            
        

        .target {
            top: anchor(50%);
        }
            
        
        

        .target {
            top: anchor(50%);
            top: calc(anchor(bottom) + 10px);
        }
        
        

        .target {
            top: anchor(50%);
            top: calc(anchor(bottom) + 10px);
            inset-block-end: anchor(start);
        }
        
        

        .target {
            top: anchor(50%);
            top: calc(anchor(bottom) + 10px);
            inset-block-end: anchor(start);
        }
        
        
        
        .target {
            top: anchor(bottom);
            top: anchor(--my-anchor bottom);
        }
        
        
        
        .target {
            top: anchor(bottom);
            top: anchor(--my-anchor bottom);
        }
        
        
        
        .target {
            top: anchor(--my-anchor bottom, 50%);
        }
        
        
        
        .target {
            top: anchor(--my-anchor bottom, 50%);
        }
        
        

🔧 Пробуем соединить

        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
            }
        
        
        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
                bottom: anchor(top);
            }
        
        

Как отцентрировать?

anchor-center

anchor-center

Значение для align свойств, при котором target-элемент центруется (насколько это возможно) относительно anchor по соответствующей оси.

CSS-спецификация
CSS-спецификация: anchor-center

anchor-center может быть применимо для

Возвращаемся к примеру

        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
                bottom: anchor(top);
            }
        
        
        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
                bottom: anchor(top);
                justify-self: anchor-center;
            }
        
        

Неплохо

        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
                bottom: anchor(top);
                justify-self: anchor-center;
            }
        
        
        
            .anchor {
                anchor-name: --my-anchor;
            }
        
            .target {
                position: absolute;
                position-anchor: --my-anchor;
                bottom: anchor(top);
                justify-self: anchor-center;
            }
        
        

Можно ли проще?

position-area

position-area

Предоставляет удобную концепцию
на основе сетки для позиционирования относительного якорного элемента.

CSS-спецификация
CSS-спецификация: position-area

.target {
    position-area: top center;
}


.target {
    position-area: top center;
    position-area: start center;
    position-area: block-start center;
}


.target {
    position-area: top center;
    position-area: start center;
    position-area: block-start center;
    position-area: y-start center;
}


.target {
    position-area: top center;
    position-area: start center;
    position-area: block-start center;
    position-area: y-start center;
}


.target {
    position-area: top center;
    position-area: start center;
    position-area: block-start center;
    position-area: y-start center;
}


.target {
    position-area: top span-left;
}


.target {
    position-area: top span-all;
}


.target {
    position-area: top;
}


.target {
    position-area: top;
}

Как оно работает?

        
        .target {
            position-area: top right;
        }
        
        
        
        .target {
            position-area: top right;
        }
        
        
        
        .target {
            position-area: top right;
        }
        
        
        
        .target {
            position-area: top right;
            left: 10%;
            bottom: 5%;
        }
        
        
Anchor tool

🏎️  Продолжаем

Как управлять размером?

anchor-size()

anchor-size()

Функция, возвращающая размеры якорного элемента.

CSS-спецификация
CSS-спецификация: anchor-size()
        
        .target {
            width: anchor-size(width);
        }
            
        
        
        
        .target {
            width: anchor-size(width);
        }
            
        
        
        
        .target {
            width: anchor-size(width);
            inline-size: anchor-size(inline);
            inline-size: anchor-size(self-inline);
        }
        
        
        
        .target {
            width: anchor-size(width);
            inline-size: anchor-size(inline);
            inline-size: anchor-size(self-inline);

            height: anchor-size(height);
            block-size: anchor-size(block);
            block-size: anchor-size(self-block);
        }
        
        
        
        .target {
            width: anchor-size(width);
        }
            
        
        
        
        .target {
            width: anchor-size(width);
            width: anchor-size(height);
        }
        
        
        
        .target {
            width: calc(anchor-size(width) * 2);
        }
        
        
        
        .target {
            width: calc(anchor-size(width) * 2);
        }
        
        
        
        .target {
            width: anchor-size(width);
            width: anchor-size(--my-anchor width);
        }
        
        
        
        .target {
            width: anchor-size(width);
            width: anchor-size(--my-anchor width);
        }
        
        
        
        .target {
            width: anchor-size(--my-anchor width, 200px);
        }
        
        
        
        .target {
            width: anchor-size(--my-anchor width, 200px);
        }
        
        

Пробуем применить

        
        .target {
            width: calc(anchor-size(width) * 2);
        }
        
        

А что по адаптивности?

Как быть?

position-try-fallbacks

position-try-fallbacks

Предоставляет список альтернативных стилей позиционирования,
которые можно попробовать применить, когда target-элемент выходит за пределы своего inset-modified containing block.

CSS-спецификация
CSS-спецификация: position-try-fallbacks

position-try-fallbacks: <try-tactic>


.target {
    position-area: top;
    position-try-fallbacks: flip-block;
}


.target {
    position-area: right;
    position-try-fallbacks: flip-inline;
}


.target {
    position-area: top center;
    position-try-fallbacks: flip-start;
}


.target {
    position-area: bottom center;
    position-try-fallbacks: flip-start;
}

position-try-fallbacks: <position-area>


.target {
    position-area:
        top span-left;
    position-try-fallbacks: 
        bottom span-right;
}

@position-try

@position-try

Определяет параметр позиции с заданным именем, указывая один или несколько наборов свойств позиционирования.

CSS-спецификация
CSS-спецификация: @position-try
        
        @position-try --try-option-name {
            property: value;
        }
        
        
        
        .target {
            width: 300px;
            position-area: top;
            position-try-fallbacks: --bottom;
        }
        
        
        
        .target {
            width: 300px;
            position-area: top;
            position-try-fallbacks: --bottom;
        }

        @position-try --bottom {
            position-area: bottom;
            margin-top: 20px;
            width: 600px;
        }
        
        

Внутри @position-try можно задавать

Position fallback и каскад

Уровни объявления стилей

Уровни объявления стилей

Как браузер определяет,
какой fallback применить?

        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        
        
        .target {
            position-area: top center;
            position-try-fallbacks: 
                --left,
                --right,
                --bottom;
        }

        @position-try --left {
            position-area: left center;
        }
        @position-try --right {
            position-area: right center;
            left: 50%;
        }
        @position-try --bottom {
            position-area: bottom center;
        }
        
        

Можем влиять на порядок применения фолбэков?

position-try-order

position-try-order

Определяет порядок применения возможных вариантов расположения.

CSS-спецификация
CSS-спецификация: position-try-order
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: normal;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-width;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-width;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-width;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-width;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-height;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-height;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-height;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        
            
                .target {
                    position-area: top center;
                    position-try-fallbacks: --left, --bottom, --right;
                    position-try-order: most-height;
                }

                @position-try --left {
                    position-area: left center;
                }

                @position-try --bottom {
                    position-area: bottom center;
                }

                @position-try --right {
                    position-area: right center;
                }
            
        

    .target {
        position-try-order: normal;

        position-try-order: most-width;
        position-try-order: most-height;
    }
        
    
    

    .target {
        position-try-order: normal;

        position-try-order: most-width;
        position-try-order: most-height;

        position-try-order: most-block-size;
        position-try-order: most-inline-size;
    }
    
    

    .target {
        position-try-order: normal;

        position-try-order: most-width;
        position-try-order: most-height;

        position-try-order: most-block-size;
        position-try-order: most-inline-size;
    }
    
    

position-try

position-try

Шортхэнд для свойств position-try-fallbacks
и position-try-order.

CSS-спецификация
CSS-спецификация: position-try
        
        .target {
            position-try: flip-inline, --bottom;
        }
            
        
        
        
        .target {
            position-try: flip-inline, --bottom;
        }
            
        
        
        
        .target {
            position-try: flip-inline, --bottom;
            position-try: most-width flip-inline, --bottom;
        }
        
        
        
        .target {
            position-try: flip-inline, --bottom;
            position-try: most-width flip-inline, --bottom;
        }
        
        

🚶🏼‍♂️ Идём дальше

Как скрыть?

position-visibility

position-visibility

Определяет, в каких случаях target-элемент должен быть скрыт.

CSS-спецификация
CSS-спецификация: position-visibility
    
    .target {
        position-visibility: always;
    }
    
    
    
    .target {
        position-visibility: no-overflow;
    }
    
    
        
        .target {
            position-anchor: --anchor;
            position-area: top center;
            position-try: flip-block;
        }
        
        
    
    .target {
        position-visibility: anchors-visible;
    }
    
    
    
    <div class="text">
        <div class="anchor">Anchor</div>
    </div>
    <div class="notes">
        <div class="target">Target</div>
    </div>  
    
    
    
    <div class="text">
        <div class="anchor">Anchor</div>
    </div>
    <div class="notes">
        <div class="target">Target</div>
    </div>  

    .anchor {
        anchor-name: --anchor;
    }

    .target {
        position-anchor: --anchor;
        top: anchor(top);
    }
    
    
    
        .target {
            position-visibility: anchors-valid;
        }
    
    
    
        .target {
            position-visibility: anchors-valid;
        }
    
    
    
        .target {
            position-visibility: anchors-valid;
        }
    
    
    
        .target {
            position-visibility: anchors-valid;
        }
    
    

Продолжаем

        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
            </li>
        </ul>
        
    
        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
            </li>
        </ul>
        
    
        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        .anchor {
            anchor-name: --anchor;
        }
        
        .target {
            position: absolute;
            position-anchor: --anchor;
            position-area: top;
        }
        
    

Почему так происходит?

Как исправить?

Неудобно

Чтож делать чтож делать

anchor-scope

anchor-scope

Ограничивает облать применения указанных якорных имён в поддереве текущего элемента.

CSS-спецификация
CSS-спецификация: anchor-scope
        
            .container {
                anchor-scope: none;
            }
        
        
        
            .container {
                anchor-scope: --a, --b;
            }
        
        
        
            .container {
                anchor-scope: all;
            }
        
        

Пробуем применить

        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        .anchor {
            anchor-name: --anchor;
        }
            
        .target {
            position: absolute;
            position-anchor: --anchor;
            position-area: top;
        }
        
    
        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        .anchor {
            anchor-name: --anchor;
        }
         
        .target {
            position: absolute;
            position-anchor: --anchor;
            position-area: top;
        }
 
        ul li {
            anchor-scope: --anchor;
        }
        
     

Ещё одно решение

        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        .anchor {
            anchor-name: --anchor;
        }
        
        .target {
            position: absolute;
            position-anchor: --anchor;
            position-area: top;
        }
    
    
        
        <ul>
            <li>
                <div class="anchor">Anchor 1</div>
                <div class="target">Target 1</div>
            </li>
            <li>
                <div class="anchor">Anchor 2</div>
                <div class="target">Target 2</div>
            </li>
            <li>
                <div class="anchor">Anchor 3</div>
                <div class="target">Target 3</div>
            </li>
        </ul>
        
    
        
        .anchor {
            anchor-name: --anchor;
        }
        
        .target {
            position: absolute;
            position-anchor: --anchor;
            position-area: top;
        }

        ul li {
            position: relative;
        }
        
    

Почему так?

Вроде разобрались

🤔 Можно использовать
  несколько якорей?

            
                    .anchor-1 {
                        anchor-name: --anchor-1;
                    }
            
        
            
                    .anchor-1 {
                        anchor-name: --anchor-1;
                    }

                    .anchor-2 {
                        anchor-name: --anchor-2;
                    }
            
        
            
                    .anchor-1 {
                        anchor-name: --anchor-1;
                    }

                    .anchor-2 {
                        anchor-name: --anchor-2;
                    }

                    .target {
                        position: absolute;
                        top: anchor(--anchor-1 bottom);
                        left: anchor(--anchor-1 right);
                        right: anchor(--anchor-2 left);
                        bottom: anchor(--anchor-2 top);
                    }
            
        
        
        /* добавляем хвостик */
        .target::after {
            content: '';
            position: absolute;
            bottom: -5px;
            left: 50%;
            transform: translate(-50%, 0px);
            transform-origin: center top;
            border-style: solid;
            border-width: 5px 5px 0px;
            border-color: yellow transparent transparent;
        }
        
        
        
        .target {
            /* ссылаемся на якорь, к которому привязан target */
            position-anchor: --anchor;
            /* делаем target якорем */
            anchor-name: --target;
        }
        /* хвостики */
        .target::before, .target::after {
            /* якоримся на тот же элемент, что и target */
            position-anchor: --anchor;
            content: '';
            position: fixed;
            background: inherit;
            margin: auto;
        }
        
        
        
        .target {
            /* ссылаемся на якорь, к которому привязан target */
            position-anchor: --anchor;
            /* делаем target якорем */
            anchor-name: --target;
        }
        /* хвостики */
        .target::before, .target::after {
            /* якоримся на тот же элемент, что и target */
            position-anchor: --anchor;
            content: '';
            position: fixed;
            background: inherit;
            margin: auto;
        }
        
        
        
        .target {
            /* ссылаемся на якорь, к которому привязан target */
            position-anchor: --anchor;
            /* делаем target якорем */
            anchor-name: --target;
        }
        /* хвостики */
        .target::before, .target::after {
            /* якоримся на тот же элемент, что и target */
            position-anchor: --anchor;
            content: '';
            position: fixed;
            background: inherit;
            margin: auto;
        }
        
        
        
        .target {
            /* ссылаемся на якорь, к которому привязан target */
            position-anchor: --anchor;
            /* делаем target якорем */
            anchor-name: --target;
        }
        /* хвостики */
        .target::before, .target::after {
            /* якоримся на тот же элемент, что и target */
            position-anchor: --anchor;
            content: '';
            position: fixed;
            background: inherit;
            margin: auto;
        }
        
        
        
        .target {
            /* ссылаемся на якорь, к которому привязан target */
            position-anchor: --anchor;
            /* делаем target якорем */
            anchor-name: --target;
        }
        /* хвостики */
        .target::before, .target::after {
            /* якоримся на тот же элемент, что и target */
            position-anchor: --anchor;
            content: '';
            position: fixed;
            background: inherit;
            margin: auto;
        }
        
        
        
        /* задаем размеры хвостиков */    
        .target::before,
        .target::after {
            left: anchor(--anchor left);
            right: anchor(--anchor right);
            width: 10px;
            max-height: 10px;
        }
        
        
        
        /* для кейса, когда target под anchor */
        .target::before {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--anchor bottom);
            bottom: anchor(--target top);
            transform: translateY(7px) rotate(45deg);
        }

        /* для кейса, когда target над anchor */
        .target::after {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--target bottom);
            bottom: anchor(--anchor top);
            transform: translateY(-7px) rotate(45deg);
        }
        
        
        
        /* для кейса, когда target под anchor */
        .target::before {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--anchor bottom);
            bottom: anchor(--target top);
            transform: translateY(7px) rotate(45deg);
        }

        /* для кейса, когда target над anchor */
        .target::after {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--target bottom);
            bottom: anchor(--anchor top);
            transform: translateY(-7px) rotate(45deg);
        }
        
        
        
        /* для кейса, когда target под anchor */
        .target::before {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--anchor bottom);
            bottom: anchor(--target top);
            transform: translateY(7px) rotate(45deg);
        }

        /* для кейса, когда target над anchor */
        .target::after {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--target bottom);
            bottom: anchor(--anchor top);
            transform: translateY(-7px) rotate(45deg);
        }
        
        
        
        /* для кейса, когда target под anchor */
        .target::before {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--anchor bottom);
            bottom: anchor(--target top);
            transform: translateY(7px) rotate(45deg);
        }

        /* для кейса, когда target над anchor */
        .target::after {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--target bottom);
            bottom: anchor(--anchor top);
            transform: translateY(-7px) rotate(45deg);
        }
        
        
        
        /* для кейса, когда target под anchor */
        .target::before {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--anchor bottom);
            bottom: anchor(--target top);
            transform: translateY(7px) rotate(45deg);
        }

        /* для кейса, когда target над anchor */
        .target::after {
            /* растягиваем хвостик между двумя якорями */
            top: anchor(--target bottom);
            bottom: anchor(--anchor top);
            transform: translateY(-7px) rotate(45deg);
        }
        
        

Use cases

UI-компоненты

Текстовые подсказки

Transition-эффекты

Визуальные подсказки

Деревья и графы

Связанные списки

Анимации и графика

Подытожим

CSS Anchor Positioning

position: absolute
и
position: fixed

Фича CSS-cвойства
anchor и target anchor-name, position-anchor
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
адаптивность местоположения position-try, position-try-fallbacks, position-try-order, @position-try
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
адаптивность местоположения position-try, position-try-fallbacks, position-try-order, @position-try
видимость position-visibility
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
адаптивность местоположения position-try, position-try-fallbacks, position-try-order, @position-try
видимость position-visibility
область применения anchor-scope
Фича CSS-cвойства
anchor и target anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
адаптивность местоположения position-try, position-try-fallbacks, position-try-order, @position-try
видимость position-visibility
область применения anchor-scope

✨ Можно использовать несколько якорей одновременно

Плюсы / минусы

Плюсы

Плюсы

Плюсы

Минусы

Плюсы

Минусы

📔 Что ещё почитать?

CSS-спецификация: anchor positioning
CSS Day 2024: Tab Atkins-Bittner – Anchor Positioning
Roman Komarov – Future CSS: Anchor Positioning
Anchoreum: игра для изучения Anchor Positioning

Приготовьте телефоны 🤳🏼

Подписаться

Рома вещает

Всем добра!

Рома Ахмадуллин

Дром

Оценить доклад