Equation for determining the dimensions (in relation to the parent) of a container with translateZ positioned within a parent container with perspective

How can the widths/heights of child elements with translateZ be calculated within a parent container that has a specified perspective value (keyword: "parallax") in relation to its parents width/height?

I am working on a website design that incorporates a parallax effect on both axes. While I have figured out most aspects of my mockup, there is one issue remaining - determining the widths/heights of the children when they exceed 100%. Due to the parent's perspective and the children's translateZ values, the visual alignment of their widths/heights is distorted.

The formula for scaling the child elements is:

1 + (translateZ * -1) / perspective
. However, I have been unable to find a formula for calculating width/height. It should be noted that everything works correctly when children's widths/heights are <= 100%.
Please refer to the image below to see the result when width >= 100% (containers have top offset for visibility).

https://i.sstatic.net/9GaM8.png

In my case, it is crucial for all child elements to visually have consistent widths/heights.


When working in SASS (preferred): PEN or SassMeister
In CSS: PEN


Relevant links from the specifications that may provide assistance:
https://www.w3.org/TR/css-transforms-1/#recomposing-to-a-3d-matrix
https://www.w3.org/TR/css-transforms-1/#mathematical-description


I have searched extensively but have not found any information leading me in the right direction. Thank you in advance...

html, body {
  height: 100%;
  overflow: hidden;
  width: 100%;
}

#projection {
  perspective: 1px;
  perspective-origin: 0 0;
  height: 100%;
  overflow: auto;
  width: 100%;
}

.pro {
  transform: scale(1) translate(0px, 0px) translateZ(0px);
  height: 100%;
  position: absolute;
  transform-origin: 0 0;
  transform-style: preserve-3d;
  width: 100%;
}

.pro--1 {
  transform: scale(4) translate(0px, 0px) translateZ(-3px);
  width: 110%;
}

.pro--2 {
  transform: scale(3) translate(0px, 50%) translateZ(-2px);
  width: 110%;
}

.pro--3 {
  transform: scale(2) translate(0px, 100%) translateZ(-1px);
  width: 110%;
}

.pro {
  background: #333;
  box-shadow: inset 0 0 0 5px orange;
  color: orange;
  font-size: 4em;
  line-height: 1em;
  text-align: center;
}

.pro--2 {
  background: rgba(75, 75, 75, 0.5);
  box-shadow: inset 0 0 0 5px green;
  color: green;
  line-height: 4em;
}

.pro--3 {
  background: rgba(75, 75, 75, 0.5);
  box-shadow: inset 0 0 0 5px white;
  color: white;
  line-height: 7em;
}
<div id="projection">
  <div class="pro pro--1">pro--1</div>
  <div class="pro pro--2">pro--2</div>
  <div class="pro pro--3">pro--3</div>
</div>

SASS

@mixin  projection($translateZ: 0, $translateX: 0, $translateY: 0, $width: 0, $height: 0, $perspective: $perspective)

  // strip and sanitize units for further calculations
  // units must be "px" for both $translateZ and $perspective
  $unit: unit( $translateZ )
  @if '' != $unit
    $translateZ: $translateZ / ($translateZ * 0 + 1)
    @if 'px' != $unit
      @warn '$translateZ must have "px" as unit!'

  $unit: unit( $perspective )
  @if '' != $unit
    $perspective: $perspective / ($perspective * 0 + 1)
    @if 'px' != $unit
      @warn '$perspective must have "px" as unit!'

  $unit: 0px // yeah - technically this is no unit
  
  // calculate scaling factor
  $scale: 1 + ($translateZ * -1) / $perspective

  // sanitize units for translateX, translateY, translateZ
  $translateZ: $translateZ + $unit
  @if unitless( $translateX )
    $translateX: $translateX + $unit
  @if unitless( $translateY )
    $translateY: $translateY + $unit

  // render css "transform: scale() translate(x, y) translateZ()"
  transform: scale( $scale ) translate($translateX, $translateY) translateZ( $translateZ + $unit )

$width: 110% // 100% works perfectly
$translateZ--1: -3 // "px" will be added in mixin
$translateZ--2: -2
$translateZ--3: -1
$perspective: 1

html, body
  height: 100%
  overflow: hidden
  width: 100%

#projection
  perspective: $perspective + 0px
  perspective-origin: 0 0
  height: 100%
  overflow: auto
  width: 100%

.pro
  @include projection()
  height: 100%
  position: absolute
  transform-origin: 0 0
  transform-style: preserve-3d
  width: 100%

.pro--1
  @include projection( $translateZ--1 )
  width: $width

.pro--2
  @include projection( $translateZ--2, 0, 50% )
  width: $width

.pro--3
  @include projection( $translateZ--3, 0, 100% )
  width: $width

Answer №1

You've successfully resolved the issue at hand. Your code is functioning as intended, and the current problem lies within the CSS layout.

Visit this link for reference.

To address the alignment discrepancies caused by perspective changes, adjusting the x-axis centering will help align all elements correctly:

(The following code modifications focus on resolving the issue)

#projection
    perspective-origin: center top

.pro
    transform-origin: center top

With these adjustments in place, the alignment has improved, but there are still slight inconsistencies - altering the $width variable to a value other than 100% such as 60% can highlight the remaining issue.

The root of the problem now stems from element positioning. When set to position: absolute, they default to aligning left due to width changes, scale additions, and transformations. To resolve this and center them effectively, include the following:

#projection
    position: relative

.pro
    left: 50%
    margin-left: $width * -.5

(For further explanation on why this centers objects, refer to this resource: CSS Trick Article)

Adjust the $width parameter as needed to verify the improvements. Testing values ranging from 20% to 150% confirms the successful resolution of the alignment issue.

Answer №2

I made some adjustments to the style for better visibility.

It looks good to me, but perhaps there is something I am not quite grasping?

html, body {
  height: 100%;
  overflow: hidden;
  width: 100%;
}

#projection {
  perspective: 1px;
  perspective-origin: 0 0;
  height: 50%;
  overflow: visible;
  width: 50%;
  margin-left: 50px;
  background-color: grey;
}

.pro {
  transform: scale(1) translate(0px, 0px) translateZ(0px);
  height: 50%;
  position: absolute;
  transform-origin: 0 0;
  transform-style: preserve-3d;
  width: 100%;
}

.pro--1 {
  transform: scale(4) translate(0px, 0px) translateZ(-3px);
  width: 110%;
}

.pro--2 {
  transform: scale(3) translate(0px, 120%) translateZ(-2px);
  width: 110%;
}

.pro--3 {
  transform: scale(2) translate(0px, 240%) translateZ(-1px);
  width: 110%;
}

.pro--1 {
  background: rgba(0, 0, 75, 0.5);
  color: blue;
  line-height: 1em;
  text-align: center;
}

.pro--2 {
  background: rgba(0, 75, 0, 0.5);
  color: green;
  line-height: 4em;
}

.pro--3 {
  background: rgba(75, 0, 0, 0.5);
  color: red;
  line-height: 7em;
}
<div id="projection">
  <div class="pro pro--1">pro--1</div>
  <div class="pro pro--2">pro--2</div>
  <div class="pro pro--3">pro--3</div>
</div>

Answer №3

An equation to determine the widths/heights of child elements containing translateZ within a parent container with a specified perspective is:
$scale =

1 + (translateZ value * -1) / perspective value
.


To apply this equation, use transform: scale( $scale ).
The perspective refers to the parent's perspective value and translateZ signifies the element's translateZ value. Refer to the snippet below or visit SASS mockup for more details.


The answer was actually provided within the question!
Although it addresses the query accurately, it may not fully resolve particular issues, leading me to ask a related question here.


Credits: @Trolleymusic who shed light on the subject with his response.


Sample CSS:

/* formula: 1 + (translateZ * -1) / perspective */

#parent {
  perspective: 10px;
}

.child--1 { /* 1 + (-100 * -1) / 10 */
  transform: translateZ(-100px) scale( 11 );
}

.child--2 { /* 1 + (-200 * -1) / 10 */
  transform: translateZ(-200px) scale( 21 );
}

.child--3 { /* 1 + (1 * -1) / 10 */
  transform: translateZ(1px) scale( 0.9 );
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is the background image on my class website too large?

I am having an issue with the redbar.png image in my CSS. It is positioned too high (within #container) and overlapping with the horizontal nav bar when it shouldn't be. I'm uncertain how to fix this problem. Any suggestions would be greatly appr ...

What is preventing internal CSS from functioning properly on mobile devices within the Gmail platform?

I have encountered an issue while sending an email from a PHP file to a Gmail account. The code I am using consists of basic HTML and CSS. Interestingly, the email looks perfect on desktop devices with all styles applied correctly. However, when viewed on ...

Photographs acting in a bizarre manner

A friend of mine encountered an issue with a website related to a school project. They were trying to set up a small gallery. The first 5 pictures displayed correctly as intended, but then they appeared like this: After testing various solutions for abou ...

The :not() selector does not currently have the capability to support complex selectors within it

Combining the CSS3 :not() selector with the attribute contains selector can be a challenge, as it seems to not work properly. Here is an example of the markup: <input type='text'/> <input type='text' id="dasd_Date_asd"/> ...

placing an empty gap within a visual depiction

My gallery lightbox displays images along with descriptions. However, the descriptions are all showing up in the same line with the same style and color. I want to separate each description on a new line to give some space. Here's an example of how th ...

Adding Php code to a Wordpress form can be done by creating a custom

I'm struggling to incorporate a PHP code into a WordPress form that I created. Despite trying three different PHP plugins, I haven't been successful. Can anyone advise on where and how to properly integrate the PHP code in WordPress and call it t ...

managing the action of a form to launch it with the help of facebox

Is there a way to use facebox to display a contact form and have the submit action also open in a facebox? Currently, I can easily open a link in a facebox using the rel attribute, like this: <a href="contact.html" rel="facebox">Contact</a> W ...

How can you modify the HTML tags before Bootstrap overrides them?

Imagine having a code snippet like this: <style> #container ul li{ font-size:50px;} .myclass1 ul li{ font-size: 20px;} </style> <div id="container"> <ul> <li> <div class="myclass1"> ...

What could be causing the image file input to appear sideways or flipped?

I am currently working on a Vuejs component that allows users to select a file from their local system. Once the user selects an image, it is previewed in a div. However, I have noticed that some images appear 'flipped' sideways automatically, es ...

Adjust the color of the navbar only after a user scrolls, with a slight delay rather than

My code changes the navbar colors when I scroll (200ms). However, I would like the changes to occur when I am slightly above the next section, not immediately. In other words, what adjustments should I make to change the color in the next section and not ...

Picture in the form of a radio button

Is there a way to use an image instead of a radio button in my AngularJS form? I have managed to hide the radio button using CSS, but it disables the checked event. How can I make the image clickable? position: absolute; left: -9999px; Here is the code s ...

Achieving a shuffling CSS animation in Angular 8 may require some adjustments compared to Angular 2. Here's how you can make it

Seeking assistance with animating an app-transition-group component in Angular 8. My CSS includes: .flip-list-move { transition: transform 1s; } Despite calling the shuffle function, the animation always happens instantly and fails to animate properly ...

Chrome is not storing the CSS file in its cache memory. However, it is successfully caching .js and .png

I have noticed that the CSS file is not being cached in the Chrome browser. My application is created using Angular-CLI and all the necessary cache-control headers are set, with an Expires header of 5 minutes: Accept-Ranges:bytes Cache-Control:max-age=600 ...

Issues with the JavaScript, HTML, and CSS Counter Implementation

Is there anyone who can assist me in making this code (available at https://jsfiddle.net/hmatrix/v3jncqac/) function properly? Purpose: My goal is to develop a counter that increments by specified values. My HTML: <body onload="incrementCount(10)"> ...

What steps can be taken to create a curved bottom for the header section?

While I've seen this question asked before, I'm not satisfied with how the design has been implemented. Here is my desired look for the curved header I've experimented with border radius left and right, but the edges are excessively rounde ...

Thumbnail vanishes upon being selected

To access my template site currently, please click here. Currently, the first thumbnail on my website is set up to display a gallery of images in FancyBox once clicked, similar to a question asked on StackOverflow that you can view here. Below is a snipp ...

Strategies for creating a dynamic progress bar using jQuery and JavaScript

I'm currently working on a project that involves increasing a percentage number while filling up the background color inside it based on the percentage value. The current setup is functional in terms of animating the background, but I need it to dynam ...

Creating Dynamic Bootstrap 4 Forms with Two Columns

I have a user registration form (Bootstrap 4 - in Razor Template) Depending on the user's selections, I will hide certain parts of the form. The registration form consists of two steps, and this is the second step. If a user selects a country withou ...

Setting the parent's height to match one of its children

I'm struggling to align the height of the pink '#images-wrap' with the main image. When there are too many small rollover images on the right, it causes the pink div to extend beyond the main image's height. If I could make them match i ...

Vertical Orientation in HTML

Would appreciate some assistance on creating a vertical text with HTML similar to the example in the linked screenshot. It needs to be straightforward and vertically oriented. Check out the screenshot for reference ...