Поддерживать выравнивание с масштабированным родным братом без обратного масштабирования - PullRequest
2 голосов
/ 11 июня 2019

У меня есть элемент, который требует масштабирования фона без масштабирования элементов в родительском элементе. Я добился этого с помощью элемента pseudo для определения фона, а затем на hover я просто масштабировал элемент pseudo. Пока все хорошо ...

Проблема в том, что мне нужно, чтобы некоторые элементы оставались на одной линии с масштабированным фоном, несмотря на то, что они сами не масштабируются. Мой первоначальный план состоял в том, чтобы просто translate их, но я быстро понял, что это невозможно из-за того, что scale основан на мультипликаторах, а translate основан на процентах / пикселях и т.д ...

Очевидное решение - отказаться от scale и вместо этого использовать маржу, чтобы уменьшить абсолютно позиционированный элемент pseudo. Тем не менее, моя оговорка в этом заключается в том, что это * плохая практика transition значение маржи.

Кто-нибудь может придумать, как я могу использовать scale, а также поддерживать выравнивание?

Обновление

Я хочу во что бы то ни стало избежать обратного / обратного масштабирования, поскольку в большинстве случаев оно плохо отображается в браузере. Имея это в виду, я не думаю, что это на самом деле возможно, но оставлю вопрос открытым, если кто-нибудь узнает о магии CSS.

См. Следующий фрагмент в качестве примера:

.tile {
  position: relative;
  width: 500px;
  height: 100px;
  padding: 40px;
}

.tile:hover:before {
  transform: scale(.9);
}

.tile:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: #000;
  z-index: -1;
  transition: transform .3s ease-out;
}

h1 {
  text-align: center;
  color: white;
}

.tile > .button {
  position: absolute;
  right: 0;
  top: 0;
  display: inline-block;
  background: red;
  padding: 10px 15px;
  color: white;
}
<div class="tile">
  <h1>Hello World</h1>
  <div class="button">Align Me</div>
</div>

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Попробуйте масштабировать .tile и изменить его потомки:

.tile {
  position: relative;
  width: 500px;
  padding: 40px;
  background: #000;
  transition: transform .3s ease-out;
}

h1 {
  text-align: center;
}

.tile>* {
  color: white;
  transition: transform .3s ease-out;
}

.tile>.button {
  position: absolute;
  right: 0;
  top: 0;
  background: red;
  padding: 10px 15px;
  color: white;
  transform-origin: 100% 0;
}

.tile:hover {
  transform: scale(.9);
}

.tile:hover>* {
  transform: scale(1.1);
}
<div class="tile">
  <section>
    <h1>Hello World</h1>
    <p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
      The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
      and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
      margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
  </section>
  <div class="button">Align Me</div>
</div>

Другая идея - анимация top и right из .button:

html,
body {
  width: 75%; 
  margin: 0;
  padding: 0
}

* {
  box-sizing: border-box
}

.tile {
  position: relative;
  width: 100%;
  padding: 40px;
  color: white;
}

.tile:hover:before {
  transform: scale(.9);
}

.tile:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: #000;
  z-index: -1;
  transition: transform .3s ease-out;
}

h1 {
  text-align: center;
}

.tile>.button {
  position: absolute;
  right: 0;
  top: 0;
  background: red;
  padding: 10px 15px;
  color: white;
  transition: .3s ease-out;
}

.tile:hover>.button {
  top: 5%;
  right: 5%
}
<div class="tile">
  <h1>Hello World</h1>
  <p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
    The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
    and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
    margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>

  <div class="button">Align Me</div>
</div>

Следующая идея заключается в использовании немного более сложного кода, но с анимацией только свойства transform:

html,
body {
  width: 75%;
}

* {
  box-sizing: border-box
}

.tile {
  position: relative;
  width: 100%;
  padding: 40px;
  color: white;
}

.tile:hover:before {
  transform: scale(.9);
}

.tile:before,
.tile>.button {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  width:100%; height:100%;  
  background: #000;
  transition: transform .3s ease-out;
}

h1 {
  text-align: center;
}

.tile>.button {
  z-index: 1;
  display: flex;
  align-items: flex-start;
  margin: 0 -100% -100% 0;
  background: transparent;
  transition: .3s ease-out;
  pointer-events: none;
}

.tile>.button div {
  padding: 10px 15px;
  background: red;
  cursor: pointer;
  pointer-events: all;
}

.tile>.button:before {
  content: '';
  flex: 1 0;
}

.tile:hover>.button {
  transform: translate3d(-5%, 5%, 0);
}
<div class="tile">
  <h1>Hello World</h1>
  <p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
    The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
    and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
    margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>

  <div class="button">
    <div>Align Me</div>
  </div>
</div>
1 голос
/ 11 июня 2019

Если вы масштабируете на p, тогда вы уменьшаете размер, и новая ширина станет width*(1 - p).Та же логика для высоты.Вы можете рассмотреть использование calc() и легко определить перевод, используя эту формулу.

Мы делим на 2, потому что мы уменьшаем с обеих сторон, и мы будем переводить с 1 стороны

.tile {
  position: relative;
  width: 540px;
  height: 200px;
  display:flex;
  align-items:center;
  justify-content:center;
}

.tile:hover:before {
  transform: scale(0.9);
}
.tile:hover .button{
  transform: translate(calc(-540px*0.1/2),calc(200px*0.1/2));
}
.tile:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: #000;
  z-index: -1;
  transition: transform .3s;
}

h1 {
  text-align: center;
  color: white;
  margin:0;
}

.tile > .button {
  position: absolute;
  right: 0;
  top: 0;
  display: inline-block;
  background: red;
  padding: 10px 15px;
  color: white;
  transition: transform .3s ;
}
<div class="tile">
  <h1>Hello World</h1>
  <div class="button">Align Me</div>
</div>

Можно использовать переменные CSS, чтобы легко изменить значение масштаба:

.tile {
  position: relative;
  width: 540px;
  height: 200px;
  display:flex;
  align-items:center;
  justify-content:center;
  --s:0.9;
}

.tile:hover:before {
  transform: scale(var(--s));
}
.tile:hover .button{
  transform: translate(calc(-540px*(1 - var(--s))/2),calc(200px*(1 - var(--s))/2));
}
.tile:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: #000;
  z-index: -1;
  transition: transform .3s;
}

h1 {
  text-align: center;
  color: white;
  margin:0;
}

.tile > .button {
  position: absolute;
  right: 0;
  top: 0;
  display: inline-block;
  background: red;
  padding: 10px 15px;
  color: white;
  transition: transform .3s ;
}
<div class="tile">
  <h1>Hello World</h1>
  <div class="button">Align Me</div>
</div>

<div class="tile" style="--s:0.5">
  <h1>Hello World</h1>
  <div class="button">Align Me</div>
</div>
...