Trouble arises when jquery's "position().top" clashes with the CSS3 property "transform: scale()"

Currently, I am working on adding a font resizer feature to my editing tool. To implement this, I made some changes to the text elements where their origin is now set to the bottom left corner. The normal version of the tool works perfectly fine, but when trying to integrate it with a zoom feature that uses transform:scale(...), some issues arise:

In the normal version, you can see that the text always stays aligned with the line regardless of the font size:

$(document).on('change', '#fontsize', function() {
  var element = $(".element");
  var fontsize = $(this).val();
  var current_top = element.position().top;
  var height = element[0].getBoundingClientRect().height;
  var bottom = current_top + height;

  console.log('font-size=' + fontsize + ' top=' + current_top + ' height=' + height);

  element.css({
    "font-size": fontsize + 'px',
  }).css({
    top: (current_top - ((current_top + element[0].getBoundingClientRect().height) - bottom)) + 'px'
  })

});
.absolute {
  position: absolute;
  left: 0px;
  width: 100%;
  border-bottom: 1px solid green;
}

.elements {
  background: #eaeaea;
  border: 1px solid red;
  position: relative;
  width: 300px;
  height: 140px;
}

.element {
  position: absolute;
  text-align: left;
  transform: rotate(0deg);
  left: 70px;
  top: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="fontsize" type="text" placeholder="Type : '21', '23' or '28'">
<span>Press enter !</span>

<div class="elements">
  <span class="absolute" style="top: 65px; z-index:999;"></span>
  <div class="element" style="">Lindow</div>
</div>

However, in the version using transform:scale(...), the behavior of element.position().top seems off as the text does not align with the line and shifts unpredictably with each change in input:

$(document).on('change', '#fontsize', function() {
  var element = $(".element");
  var fontsize = $(this).val();
  var current_top = element.position().top;
  var height = element[0].getBoundingClientRect().height;
  var bottom = current_top + height;

  console.log('font-size=' + fontsize + ' top=' + current_top + ' height=' + height);

  element.css({
    "font-size": fontsize + 'px',
  }).css({
    top: (current_top - ((current_top + element[0].getBoundingClientRect().height) - bottom)) + 'px'
  })

});
.elements {
  transform:scale(1.5); 
  transform-origin:top left;
}

.absolute {
  position: absolute;
  left: 0px;
  width: 100%;
  border-bottom: 1px solid green;
}

.elements {
  background: #eaeaea;
  border: 1px solid red;
  position: relative;
  width: 300px;
  height: 140px;
}

.element {
  position: absolute;
  text-align: left;
  transform: rotate(0deg);
  left: 70px;
  top: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script>
<input id="fontsize" type="text" placeholder="Type : '21', '23' or '28'">
<span>Press enter !</span>

<div class="elements">
  <span class="absolute" style="top: 65px; z-index:999;"></span>
  <div class="element" style="">Lindow</div>
</div>

I'm currently looking for a solution to fix this issue. Any insights on what might be causing this problem and how to address it would be greatly appreciated.

Answer №1

Adjusting the font size of an element can impact its height, especially when using absolute positioning. It's recommended to work from the bottom position rather than the top.

To simplify the script, I updated it to set bottom: 72px in the .element rule.

Keep in mind that the space between the text bottom and the green line is influenced by the font and increases with the font size due to internal metrics. This behavior is normal and varies across different font types. If you need to adjust for this variation, you may have to calculate and incorporate the specific font values into your measurements, considering potential differences between browsers and operating systems.


Original Version

$(document).on('change', '#fontsize', function() {
  var element = $(".element");
  var fontsize = $(this).val();
  
  console.log('font-size=' + fontsize);

  element.css({
    "font-size": fontsize + 'px',
  })

});
.absolute {
  position: absolute;
  left: 0px;
  width: 100%;
  border-bottom: 1px solid green;
}

.elements {
  background: #eaeaea;
  border: 1px solid red;
  position: relative;
  width: 300px;
  height: 140px;
}

.element {
  position: absolute;
  text-align: left;
  transform: rotate(0deg);
  left: 70px;
  bottom: 72px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="fontsize" type="text" placeholder="Type : '21', '23' or '28'">
<span>Press enter !</span>

<div class="elements">
  <span class="absolute" style="top: 65px; z-index:999;"></span>
  <div class="element" style="">Lindow</div>
</div>


Scaled Version

$(document).on('change', '#fontsize', function() {
  var element = $(".element");
  var fontsize = $(this).val();
  
  console.log('font-size=' + fontsize);

  element.css({
    "font-size": fontsize + 'px',
  })

});
.elements {
  transform:scale(1.5); 
  transform-origin:top left;
}

.absolute {
  position: absolute;
  left: 0px;
  width: 100%;
  border-bottom: 1px solid green;
}

.elements {
  background: #eaeaea;
  border: 1px solid red;
  position: relative;
  width: 300px;
  height: 140px;
}

.element {
  position: absolute;
  text-align: left;
  transform: rotate(0deg);
  left: 70px;
  bottom: 72px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="fontsize" type="text" placeholder="Type : '21', '23' or '28'">
<span>Press enter !</span>

<div class="elements">
  <span class="absolute" style="top: 65px; z-index:999;"></span>
  <div class="element" style="">Lindow</div>
</div>


Updated Information

If you prefer to base calculations on the top value, you'll need to consider the scale() value and adjust the top value based on the difference between old and new height values.

$(document).on('change', '#fontsize', function() {
  var element = $(".element");
  var scale = (element[0].getBoundingClientRect().width / element[0].offsetWidth);  
  var fontsize = $(this).val();
  var top = element.position().top / scale;
  var height = element[0].getBoundingClientRect().height / scale;

  element.css({
    "font-size": fontsize + 'px',
  }).css({
    top: top - ((element[0].getBoundingClientRect().height / scale) - height) + 'px'
  })

});
.elements {
  transform:scale(1.5); 
  transform-origin:top left;
}

.absolute {
  position: absolute;
  left: 0px;
  width: 100%;
  border-bottom: 1px solid green;
}

.elements {
  background: #eaeaea;
  border: 1px solid red;
  position: relative;
  width: 300px;
  height: 140px;
}

.element {
  position: absolute;
  text-align: left;
  transform: rotate(0deg);
  left: 70px;
  top: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="fontsize" type="text" placeholder="Type : '21', '23' or '28'">
<span>Press enter !</span>

<div class="elements">
  <span class="absolute" style="top: 65px; z-index:999;"></span>
  <div class="element" style="">Lindow</div>
</div>

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

What is the best way to execute an ajax call in a Ruby on Rails application?

Hey there, I am just starting to learn Ruby on Rails and I need help with making an ajax request. Here is the JavaScript code I have: $(document).ready(function(){ $(".form_submit").click(function() { var apiid = $('#apiid').val(); ...

Unable to get jQuery date picker to function on dynamically generated input fields through ajax

I'm facing an issue with my jQuery date picker not working on an input field generated via Ajax from the server-side, but it works fine when the field is directly added to the page. Here's a simplified version of what I'm dealing with: The ...

Ensuring Form Validation in Symfony 2.0 View

I am currently using Symfony 2.0 and I have a view file called test.html.php which includes a form: <form action="" method="post" rel=""> <input type="hidden" name="action" value="test" /> <input name="myinput" type="text" value="" ...

Populating hidden fields in Javascript with mouseover event trigger - Pre-click action

Seeking a solution for another issue, I stumbled upon the capability to execute JavaScript on mouseover. Here is what I want to execute: $(document).ready(function(){ function myPayment() { var value = document.mortgagecalc.value_input.value; var rate ...

Variations between <div/> and <div></div>

When using Ajax to load two divs, I discovered an interesting difference in the way they are written. If I write them like this: <div id="informCandidacyId"/> <div id="idDivFiles"/> Although both divs are being loaded, only one view is added ...

elements of bootstrap overlapping one another

I have created a website using Bootstrap, which can be accessed at this link. The homepage is experiencing alignment issues, with sections colliding with each other. To prevent this collision, I had to add margin-top like the example below: ...

There is an issue with the function of elem.autocomplete - it is not recognized

I'm new to Angular.JS and have been struggling for the past 6 hours. I've been working on reading data from an HTTP source and displaying it as an autocomplete feature on the view. Previously, the data was displayed in a select box, but I decide ...

Move each four-character IT value to a new line

const maxNumLength = 4; event = jQuery.Event("keypress") event.which = 13 $('#input').on('input focus keydown keyup', function() { const inputValue = $(this).val(); const linesArray = inputValue.split(/(&bsol ...

Accessing Properties in React.js: A Guide

<Element id="1" onClick={this.runFunction(???)}/> When the onClick event is triggered, I want to execute a different function with the key value "1" as an argument. How can I make this happen? Thank you. ...

Make an axios request multiple times equal to the number of items in the previous response

In my project, I am using the axios library to convert addresses into their respective coordinates. First, I fetch a list of addresses from an API. Next, I take the RESPONSE object and use Google API to convert each address to coordinates. Finally, I wan ...

Restricting or postponing HTTP requests in an AngularJS service

I recently developed a service for my AngularJS app that retrieves data by making $http calls through various methods. However, I encountered an issue where these requests were being triggered every time an HTML element in the view (a product details div) ...

Sending the selected option from a dropdown menu to populate a textbox on a separate webpage using PHP, jQuery, and AJAX

I am looking to dynamically update the value of a dropdown in index.php to a textbox in test.php using Ajax. The scenario involves having test.php embedded as an iframe within index.php. Upon changing the dropdown selection, the corresponding value should ...

selecting unique elements using classes is not possible with jquery

I am experimenting with using ajax on dynamically generated html elements from django. I have tried selecting the instances by class, but for some reason, it is not working as expected. Can anyone point out my mistake here? javascript $(document).ready(fu ...

Toggle menu visibility when body is clicked

<script> $(".bg").on('click', function(e) { e.preventDefault(); $("#navMenu").removeClass('open'); $("#searchBar").removeClass('active'); }); </script> My goal is to togg ...

The iron-session package does not export the path ./next/dist from the package

I am encountering an issue while using iron-session. Below is the code snippet causing the error: import { withIronSessionSsr } from 'iron-session/next/dist'; ... export const getServerSideProps = withIronSessionSsr(async function ({ req, r ...

When dynamically accessed, the property of a JSON object is considered "undefined"

I'm running into trouble trying to access properties of a JSON object in my JavaScript code using obj[varWithPropName]. Strangely, it does work when I use obj["PropName"]. Here's a simplified snippet for reference: import * as CharInfo from &ap ...

Expanding parent nodes in Jstree to load child nodes dynamically (json)

I am trying to optimize the performance by loading the child nodes of a parent node only after clicking on that specific parent node. It is important because there are many child nodes, so this method helps in keeping the performance high. Currently, I ha ...

Enhance the appearance of a custom checkbox component in Angular

I developed a customized toggle switch for my application and integrated it into various sections. Recently, I decided to rework it as a component. However, I am encountering an issue where the toggle switch button does not update in the view (it remains t ...

Printing content using JavaScript on a point of sale (POS) printer with

I need to print a specific div on my POS printer named Optimuz. I have attempted using the following code: <div id="printAreaInvoice" style="visibility: hidden;font-size:8px;width:200px;"></div> < ...

Angular 10: A guide to dynamically highlighting navbar elements based on scrolling position

I am currently working on a single-page application using Angular 10. I have a simple page layout and I want to implement a feature that will highlight the navbar based on the scroll position. How can I achieve this functionality in a single-page applicati ...