'transform3d' не працює з позицією: фіксовані діти


140

У мене є ситуація, коли за звичайних обставин CSS фіксований div розміщуватиметься саме там, де він вказаний ( top:0px, left:0px).

Здається, це не дотримується, якщо у мене є батько, який має translate3d перетворення. Хіба я чогось не бачу? Я спробував інші варіанти перетворення веб-файлів, такі як стиль та перетворення походження, але не пощастило.

Я додав JSFiddle із прикладом, коли я б очікував, що жовте поле буде у верхньому куті сторінки, а не всередині елемента контейнера.

Нижче ви можете знайти спрощену версію загадки:

#outer {
    position:relative; 
    -webkit-transform:translate3d(0px, 20px , 0px); 
    height: 300px; 
    border: 1px solid #5511FF; 
    padding: 10px;
    background: rgba(100,180,250, .8); 
    width: 80%;
}
#middle{
    position:relative; 
    border: 1px dotted #445511; 
    height: 300px; 
    padding: 5px;
    background: rgba(250,10,255, .6);
}
#inner {
    position: fixed; 
    top: 0px;
    box-shadow: 3px 3px 3px #333; 
    height: 20px; 
    left: 0px;
    background: rgba(200,180,80, .8); 
    margin: 5px; 
    padding: 5px;
}
<div id="container">
    Blue: Outer, <br>
    Purple: Middle<br>
    Yellow: Inner<br>
    <div id="outer"> 
        <div id="middle">
            <div id="inner">
                Inner block
            </div>
        </div>
    </div>
</div>

Як я можу змусити роботу translate3d з дітьми з фіксованим розташуванням?


Те ж проблема виникає з фільтром теж: stackoverflow.com/q/52937708/8620333
Феманітяне Afif

Відповіді:


196

Це тому, що transformстворюється нова локальна система координат відповідно до специфікації W3C :

У просторі імен HTML будь-яке значення, окрім noneтрансформації, призводить до створення контексту укладання та блоку, що містить. Об'єкт виконує роль блоку, що містить фіксовану позицію нащадків.

Це означає, що нерухоме позиціонування стає фіксованим на перетворений елемент, а не на область перегляду.

Наразі немає відомості про те, про що я знаю.

Це також задокументовано у статті Еріка Мейєра: Відкріплення виправлених елементів за допомогою перетворень CSS .


Дякую, я не помітив, що фактична специфікація мала цю інформацію ..... Я здогадуюсь, що отримав еквівалент математичній відповіді: "за визначенням" :)
Хуан Карлос Морено

3
@INT, я не думаю, що цього не вдасться вирішити. Існує головний випадок використання заборони обхідних шляхів: надані користувачем дані можуть потенційно охоплювати елементи керування за межами визначеної області (подумайте, що зловмисне повідомлення електронної пошти додає параметри на панелі інструментів gmail). Найкращим рішенням було б уникати перетворень на даний момент, якщо ви збираєтесь використовувати фіксовану зсередини.
saml

1
Не вдалося б встановити верхній атрибут CSS у будь-який window.scrollHeight, що працює? Можливо, вам доведеться абсолютно позиціонувати його, але щось подібне повинно бути виконано, чи не так? (занадто ліниво, щоб насправді випробувати зараз)
Бред Орего

@bradorego ви мали рацію, я просто додав код, який я використав.
UzumakiDev

Наскільки я можу сказати, це все ще знаходиться в потоці в специфікації. Див. Bug 16328 - Використання "містить блок" не відповідає визначенню CSS2.1 .
третій

13

У мене було мерехтіння на моєму фіксованому верхньому наві, коли елементи на сторінці використовували перетворення, наступне, застосоване до мого верхнього нав, вирішило проблему стрибків / мерехтіння:

#fixedTopNav {
    position: fixed;
    top: 0;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

Завдяки цій відповіді на ТАК


12

Як запропонував Брадоерго, просто дістаньте вікно scrollTopта додайте його до абсолютної позиції вгорі:

function fix_scroll() {
  var s = $(window).scrollTop();
  var fixedTitle = $('#fixedContainer');
  fixedTitle.css('position','absolute');
  fixedTitle.css('top',s + 'px');
}fix_scroll();

$(window).on('scroll',fix_scroll);

Це все одно працювало на мене.


3
Це працює! але замість прив’язки до «вікна», я повинен був прив’язатись до діва, який прокручувався. Також нерухомий елемент мерехтить.
поїзд

Що тут має робити jQuery?
FlorianB

Це могло б зробити це, але як згадується @train, воно мерехтить.
Етьєн Дюпуа

Так, це не оновлюється майже швидко, щоб бути достатньо чистим для мого використання: - / хороша ідея Тхо
рейд

Це дуже погана практика, не змінюйте стилі з js
Wannes

4

У Firefox та Safari ви можете використовувати position: sticky;замість них, position: fixed;але це не працюватиме в інших браузерах. Для цього вам потрібен JavaScript.


2
Клейке позиціонування - це гібрид відносного і фіксованого позиціонування, і це дійсно експериментально , я б дуже рекомендував цього не уникати, оскільки це ще не є стандартним.
Farside

1
AFAIK на Firefox та Safari ви можете просто використовувати, position:fixedі він буде працювати, як і очікувалося.
oriadam

@oriadam ні, у мене є проблема, коли батько використовує translate3d, а фіксована позиція дітей летить навколо. Постараємося використовувати, stickyпоки це "вже підтримується основними браузерами: caniuse.com/#feat=css-sticky
Лукас Лієсіс

stickyЦе може бути рішенням, воно працює в сучасному браузері.
aboutqx

3

На мою думку, найкращий спосіб вирішити це - застосувати той самий переклад, але розбити дітей, які потрібно виправити з батьківського (перекладеного) елемента; а потім застосувати переклад до діва всередині position: fixedобгортки.

Результати виглядають приблизно так (у вашому випадку):

<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'> 

</div>
<div style='position: fixed; top: 0px; 
            box-shadow: 3px 3px 3px #333; 
            height: 20px; left: 0px;'>
    <div style='-webkit-transform:translate3d(0px, 20px, 0px);'>
        Inner block
    </div>
</div>

JSFiddle: https://jsfiddle.net/hju4nws1/

Хоча це може бути не ідеально для деяких випадків використання, зазвичай, якщо ви виправляєте div, ви, ймовірно, могли б менше піклуватися про те, який елемент є його батьком / де він потрапляє у дерево спадкування у вашому DOM, і, здається, вирішує більшість головного болю - при цьому ще дозволяючи обом translateі position: fixedжити у (відносній) гармонії.


0

Я зіткнувся з тією ж проблемою. Єдина відмінність полягає в тому, що мій елемент із "позицією: фіксований" мав свої "верхній" та "лівий" властивості стилю, встановлені з JS. Тож я зміг застосувати виправлення:

var oRect = oElement.getBoundingClientRect();

oRect об'єкт буде містити реальну (щодо порту перегляду) верхню та ліву координати. Таким чином, ви можете налаштувати фактичні властивості oElement.style.top та oElement.style.left.


Це працює на IE та Chrome, але не на стандартному браузері Android. Зліва - це число, але воно завжди намальоване на позиції 0
Адаптабі

0

У мене є бічна панель полотна, яка використовує -webkit-transform: translate3d. Це заважало мені розміщувати фіксований колонтитул на сторінці. Я вирішив проблему, орієнтуючись на клас на html-сторінці, який додається до тегу при ініціалізації бічної панелі, а потім записав css: not kvalifier, щоб вказати "-webkit-transform: none;" до тегу html, коли цього класу немає у тезі html. Сподіваюся, це допоможе комусь там із цим самим питанням!


0

Спробуйте застосувати протилежне перетворення до дочірнього елемента:

<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'> 
    <div style='position: fixed; top: 0px; 
                -webkit-transform:translate3d(-100%, 0px , 0px); 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'>
        Inner block
    </div>
</div>

0

Додайте динамічний клас, поки елемент перетворюється. $('#elementId').addClass('transformed'). Потім продовжуйте оголошувати в css,

.translat3d(@x, @y, @z) { 
     -webkit-transform: translate3d(@X, @y, @z); 
             transform: translate3d(@x, @y, @z);
      //All other subsidaries as -moz-transform, -o-transform and -ms-transform 
}

тоді

#elementId { 
      -webkit-transform: none; 
              transform: none;
}

тоді

.transformed {
    #elementId { 
        .translate3d(0px, 20px, 0px);
    }
}

Тепер, position: fixedколи надаються значення a topта z-indexвластивості дочірнього елемента, просто працюють добре і залишаються фіксованими, поки батьківський елемент не трансформується. Після повернення перетворення дочірній елемент з'являється як фіксований знову. Це може полегшити ситуацію, якщо ви фактично використовуєте бічну панель навігації, яка перемикається та закривається після клацання, і у вас є набір вкладок, який повинен залишатися липким під час прокручування сторінки.


-1

Один із способів вирішити це - застосувати те саме перетворення до нерухомого елемента:

<br>
<div style='position:relative; border: 1px solid #5511FF; 
            -webkit-transform:translate3d(0px, 20px , 0px); 
            height: 100px; width: 200px;'> 
    <div style='position: fixed; top: 0px; 
                -webkit-transform:translate3d(0px, 20px , 0px); 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'>
        Inner block
    </div>
</div>

1
У IE помилка не існує в першу чергу
oriadam
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.