Adjust an SVG text to fit perfectly within an SVG background rectangle

Inside this box are two SVGs: one for the text and one for the background rectangle.

My goal is to make sure the text fits perfectly within the background rectangle without any stretching or overflowing. I don't want to break the text into multiple lines - I want to adjust the size of the text to fit it all in a single line.

Despite trying numerous solutions without success, I'm open to using JavaScript if necessary to solve this issue with the text and background rectangle both being SVGs.

Note: It is essential for both the text and background rectangle to remain as SVGs.

Here is the CodePen link for reference.

Below you can find the code snippet:

@font-face {
  font-family: "Heebo-Light";
  src: url(Heebo-Light.ttf) format("truetype");
}

svg {
    position: relative;
    display: block;
    overflow: visible;
    pointer-events: none;
}

body {
  background-color: #FDFDFD;
  overflow: hidden;
}

.box svg:nth-of-type(1) {
  position: absolute;
  z-index: 3;
}

.box svg:nth-of-type(2) {
  position: absolute;
  z-index: 2;
}

.box, svg {
  max-width: 100%;
  max-height: 2.59vw;
}

.box {
  position: relative;
  height: 2.59vw;
}
<div id="box-13" class="box" style="width: 35.0663246486498vw;">
   <svg height="100%" width="100%" viewBox="0 0 100 45">
      <text font-family="Heebo-Light" font-size="24px" fill="#595959" fill-opacity="1" x="50%" y="53%" dominant-baseline="middle" text-anchor="middle">
         <tspan id="span-15">This is a long text that should be fit This is a long text that should be fit This is a long text that should be fit</tspan>
      </text>
   </svg>
   <svg height="100%" width="100%" viewBox="0 0 272 45" preserveAspectRatio="none">
      <defs>
         <linearGradient gradientTransform="rotate(90, 0.5, 0.5)" id="uniqueDomIdA-4">
            <stop offset="0%" stop-color="#AFAFAF" stop-opacity="1"></stop>
            <stop offset="0%" stop-color="#F5F3F8" stop-opacity="1"></stop>
            <stop offset="69.804%" stop-color="#F9F9F9" stop-opacity="1"></stop>
            <stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"></stop>
         </linearGradient>
         <filter id="uniqueDomIdB-4" filterUnits="userSpaceOnUse" x="-15.75" y="-15.75" width="303.5" height="76.5">
            <feFlood result="floodOut" flood-color="#CCC1DA" flood-opacity="0.29"></feFlood>
            <feGaussianBlur result="gaussOut" in="SourceAlpha" stdDeviation="2.450000047683716,2.450000047683716">
            </feGaussianBlur>
            <feComposite in="floodOut" in2="gaussOut" operator="in"></feComposite>
         </filter>
      </defs>
      <use transform="translate(-2.72, -0.45) scale(1.0199999809265137, 1.0199999809265137) translate(0, 0)" xlink:href="#uniqueDomIdC-4" filter="url(#uniqueDomIdB-4)" data-angle="0" data-distance="0" data-height="45" data-scale="1.02" data-adornment-type="drop-shadow" data-width="272" data-transform="[{&quot;type&quot;:&quot;translate&quot;,&quot;args&quot;:[-2.72,-0.45]},{&quot;type&quot;:&quot;scale&quot;,&quot;args&quot;:[1.0199999809265137,1.0199999809265137]}]"></use>
      <g id="uniqueDomIdC-4">
         <g>
            <path d="M0,0L272,0 272,45 0,45z" fill="url(#uniqueDomIdA-4)"></path>
         </g>
      </g>
   </svg>
</div>

Edit: Modifying the viewBox property shows potential, but I'm unsure how to calculate its values. While I can determine the width of the box, viewBox calculation remains a mystery to me. Any advice on this matter would be greatly appreciated.

Answer №1

Due to the small size of the box and the lengthy text, the text may barely be visible.

To determine the length of the text in JavaScript, I am using: span15.getComputedTextLength() and utilizing this value for the viewBox attribute.

let text_length = span15.getComputedTextLength();

document.querySelector("#first").setAttribute("viewBox",`0 0 ${text_length} 45`)
@font-face {
  font-family: "Heebo-Light";
  src: url(Heebo-Light.ttf) format("truetype");
}

svg {
    position: relative;
    display: block;
    overflow: visible;
    pointer-events: none;
    outline:solid red;
}

body {
  background-color: #FDFDFD;
  overflow: hidden;
}
.box {
  position: relative;
  height: 2.59vw;
  outline:solid;
}
<div id="box-13" class="box" style="width: 35.0663246486498vw;">
   <svg id="first" viewBox="0 0 100 45">
      <text font-family="Heebo-Light" font-size="24px" fill="#595959" fill-opacity="1" x="50%" y="53%" dominant-baseline="middle" text-anchor="middle">
         <tspan id="span15">This is a long text that should be fit This is a long text that should be fit This is a long text that should be fit</tspan>
      </text>
   </svg>
  </div>

Answer №2

<div id="box-13" class="box" style="width: 35.0663246486498vw;">
  <svg height="100%" width="100%" viewBox="0 0 272 45" preserveAspectRatio="none">
      <defs>
         <linearGradient gradientTransform="rotate(90, 0.5, 0.5)" id="uniqueDomIdA-4">
            <stop offset="0%" stop-color="#AFAFAF" stop-opacity="1"></stop>
            <stop offset="0%" stop-color="#F5F3F8" stop-opacity="1"></stop>
            <stop offset="69.804%" stop-color="#F9F9F9" stop-opacity="1"></stop>
            <stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"></stop>
         </linearGradient>
         <filter id="uniqueDomIdB-4" filterUnits="userSpaceOnUse" x="-15.75" y="-15.75" width="303.5" height="76.5">
            <feFlood result="floodOut" flood-color="#CCC1DA" flood-opacity="0.29"></feFlood>
            <feGaussianBlur result="gaussOut" in="SourceAlpha" stdDeviation="2.450000047683716,2.450000047683716">
            </feGaussianBlur>
            <feComposite in="floodOut" in2="gaussOut" operator="in"></feComposite>
         </filter>
      </defs>
      <use transform="translate(-2.72, -0.45) scale(1.0199999809265137, 1.0199999809265137) translate(0, 0)" xlink:href="#uniqueDomIdC-4" filter="url(#uniqueDomIdB-4)" data-angle="0" data-distance="0" data-height="45" data-scale="1.02" data-adornment-type="drop-shadow" data-width="272" data-transform="[{&quot;type&quot;:&quot;translate&quot;,&quot;args&quot;:[-2.72,-0.45]},{&quot;type&quot;:&quot;scale&quot;,&quot;args&quot;:[1.0199999809265137,1.0199999809265137]}]"></use>
      <g id="uniqueDomIdC-4">
         <g>
            <path d="M0,0L272,0 272,45 0,45z" fill="url(#uniqueDomIdA-4)"></path>
      <foreignObject
        x="0" y="0" width="100%" height="100%"
      >
          <p style="font-size: 1.8vw;line-height:1.2;text-align:center;">This is a lengthy text that needs to be adjusted This is a lengthy text that needs to be adjusted This is a lengthy text that needs to be adjusted</p>
       
      </foreignObject>
         </g>
      </g>
   </svg>
</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

The variable "require" has not been declared in npm.js file at line

Apologies if this is a simple issue, but I have not been able to find a solution in my research. I am using the latest release of Bootstrap and have noticed a new file called npm.js compared to previous versions. All Bootstrap files are hosted locally on m ...

Reorganize the placement of table columns between different rows

I am currently using a software program that automatically generates a form based on the selected options. The code for this form is generated in tables, which I am unable to directly edit. However, I would like to have the Amount, radio buttons, and their ...

Exploring the concept of clip-path

Recently, I have been delving into the world of HTML and CSS, exploring clip-paths after stumbling upon them on this captivating website. My interpretation is that utilizing clip-paths, particularly with the polygon attribute, enables one to control which ...

Node version 6.11.0 experiencing JavaScript heap error even with zero memory usage in the program

Encountering an out of memory error even though only two variables (i & j) are being used. Can someone please provide clarification? I am not storing anything in memory or saving it to any storage; whatever is generated is outputted to the console and the ...

Incorporate tinyMCE into a colorbox module

Currently, I am facing an issue on my website where there are textareas with tinymce. While I can view all the textareas correctly, when trying to open colorbox within a textarea, it does not inherit the tinymce properties. The code snippet used to open co ...

Steps for incorporating error messages in jQuery Validator:1. Begin by including the

I am currently facing an issue with displaying error messages on my "contact me" form. Although I have successfully implemented validation, I am struggling to comprehend how the errorPlacement function should be utilized. Could someone provide me with a ...

Transforming into a serialized division

I am working on creating a custom WISYWIG editor that generates a div with specific inner elements. The goal is to design the div (along with its inner structure), serialize it, store it in a database as a string or JSON format, and later insert it into th ...

Creating a dynamic link in Vue JS is a cinch!

I currently have the following code snippet: <b-dropdown text="Select Factory" block variant="primary" class="m-2" menu-class="w-100"> <b-dropdown-item @click="selectedFactory='China'"> ...

Optimal asset management strategies for Angular applications

What is the process for loading assets in an Angular app? Will the app wait for all assets to load before bootstrapping, or will they be lazy loaded if not needed on the initial page? I have a large number of PDFs stored in the assets folder that I load a ...

Error Alert: The combination of React and Redux-router is causing an unexpected issue. The reducer is expected to be a

Whenever I make a coding mistake and encounter a runtime error, the error reporting is not very helpful. For example, when I mistakenly typed Date() instead of new Date(), the error message I received was... Uncaught Error: Expected the reducer to be a fu ...

I am unable to access the properties of an undefined element, specifically the 'size' property in Next.js 13

I encountered a problem today while working with Next.js version 13.4 and backend integration. When using searchParams on the server side, I received an error message: "Cannot read properties of undefined (reading 'size')" while destructuring siz ...

Close the menu located in the menu bar under the Home section

I am struggling with creating the bootstrap collapse menu. <div className='collapse' id='mobile-menu'> <button clasNames='navbar-toggler' type='button' data-togg ...

Attempting to utilize express-load in conjunction with express 4

As a beginner in NodeJS, I encountered a problem with my code. Let me show you the issue. I am trying to load the application in the MVC pattern using express-load, but I am facing an error when defining the load order. Here is the important part of app. ...

When using Express.js for file uploading, it is important to first verify that a file has been sent, set a maximum file size limit, and ensure

After working with expressjs for a month, I've encountered some issues with file uploads. Despite researching on Google and various blogs, I haven't been able to find answers to the following three questions: What do I need to do or what setting ...

Learning how to utilize various types of buttons in C# and ASP.NET with this

I was following this tutorial: I like everything the same except I want to make the following change: <section> <a rel="external" href="#button" id="button">&#xF011;</a> <span></span> </section> ...

CSS Grid with dynamically changing number of rows set to "auto", while ensuring one row always has a fixed size of "1fr"

Currently, I am experimenting with a CSS grid-based frontend and have encountered a specific requirement that keeps repeating itself in various parts of the frontend: A grid with a dynamic number of rows. Each row should be of variable size (auto). The f ...

How can the target pseudo-class be utilized to replace the 'active' state on navigation across several pages effectively?

Within a large application, I am managing a micro site and looking to implement tertiary navigation with an active state for pages. This involves inserting a single html blob into multiple pages. My goal is to use an active class to highlight the page in ...

The process of converting a string containing a list of object properties into separate objects using JavaScript

I am trying to transform the following string into actual objects. It seems that JSON.parse is not functioning as expected because all the properties are grouped together in a single string instead of being separate. This text string is retrieved from an A ...

What could be causing my fixed element to disappear when the webpage is not long enough?

OBJECTIVE: a div is { position:fixed; bottom:0% } it has a genuine height and width; the z-index is the highest in the document = so, it should always be visible! ISSUE: mobile browsers 'cut' the bottom end of the page when zooming out. ...

Guide to Triggering a Page View Event in Google Tag Manager with Angular

Previously, I manually fired the Page View Event using JavaScript from app.component.ts while directly accessing Google Analytics: declare var gtag: Function; ... constructor(private router: Router) { const navEndEvents = this.router.events.pipe( fil ...