Creating a dynamic sidebar in wkhtmltopdf that tracks a changing text span

I am currently working on incorporating a sidebar to the left side of a generated PDF whenever there is text enclosed within a span with the class name sidebar. One major issue I am encountering is that when the text spans across multiple lines, calculating the height or coordinates of the span in JavaScript within wkhtmltopdf results in inaccurate values. This makes it difficult for me to accurately size or position the generated sidebar element. I am open to any suggestions or ideas that could help me resolve this issue.

Some of the approaches I have experimented with include:

  • Creating the sidebar as a :before pseudo-element within the span (as shown below). When setting the span's position to relative and the :before pseudo-element to absolute with properties like height: 100% and left: 0, it does create a bar that matches the height of the span but it appears inside the span and I struggle to find the correct left offset value to reposition the bar. In wkhtmltopdf, the getBoundingClientRect().left and offset().left return values such as 8 for the :before element (possibly due to page margin) and 0 for its parent span.
  • Implementing the sidebar as a :before pseudo-element without setting its parent to relative. While the sidebar does appear at the left edge of the PDF in this scenario, I face challenges in determining the accurate height of the span to apply to the sidebar. For instance, a 3-line span may return a height of over a thousand pixels when using offsetHeight. Similar issues arise when subtracting getBoundingClientRect().top from getBoundingClientRect().bottom. Block elements exhibit the same behavior, suggesting that wkhtmltopdf boxes extend to the bottom of the page.
  • Employing the sidebar as a :before pseudo-element, positioned absolutely at the left edge of the page and resized by inserting line breaks into the content style to match the number of soft breaks in the span using getClientRects(). Within wkhtmltopdf, getClientRects().length may yield unexpected values, such as 63 for a 3-line span.
  • Adding two div elements before and after detecting the span, followed by utilizing canvas to draw a line between them. However, this approach encountered roadblocks when the second div returned negative values for offset().top.
  • Regarding the JavaScript, I have experimented with both embedding it in the document and executing it from the command line using --run-script. Unfortunately, I encountered similar issues in both cases.

<style>
  .sidebar { position: relative; background-color: yellow; }
  .sidebar::before { position: absolute; content: ''; border-left: 2px #000 solid; left: 0; height: 100%; }
</style>

<body>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. <span class="sidebar">Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</span> Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</body>

Here's a visual representation of my desired outcome. The left sidebar here matches the height of the highlighted yellow text.

Answer №1

Here is the code snippet:

</<!DOCTYPE html>
<html>

<head>
    <style>
        body {
            height: 842px;
            width: 595px;
        }

        .sidebar {
            background-color: yellow;
        }

        .sidebar::before {
            position: fixed;
            content: '';
            border-left: 2px #000 solid;
            left: 0;
        }
    </style>
</head>

<body>
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
    <span class="sidebar">Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
    </span> Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

    <script>
        document.addEventListener("DOMContentLoaded", function(event) {
            var span = document.getElementsByClassName('sidebar')[0];
            document.styleSheets[0].addRule('.sidebar::before', 'height: ' + span.offsetHeight + 'px;');
        });
    </script>
</body>


</html>

Note: An additional body style of height and width was added for better compatibility with wkhtmltopdf javascript to display the correct span.offsetHeight. This adjustment was necessary as without it, the height appeared larger than expected.

During testing in Chrome, the body style wasn't required like for wkhtmltopdf. As per requirements, you can adjust the width/height pixels accordingly, considering any margins present.

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 there a way to determine which label in the Material UI default theme affects the default border color, specifically excluding the focus or hover border?

I am currently using the 'createTheme' function to personalize the theme of my TextField input component in Material UI. To implement the desired changes, I am referring to the default theme for Material UI on https://mui.com/customization/defau ...

"Optimizing navigation with dynamic link routing in AngularJS

I am working on a list of apartments displayed using ng-repeat. I need each apartment to be a clickable link that directs the user to view more details about that specific apartment. However, I am facing an issue where the links are not being repeated dyna ...

unable to use 'await' keyword to delay the code execution until a function finishes

I'm encountering an issue where I need to wait for the result of a local function before proceeding further. Here is the code for the local function: var Messagehome = (req, res) => { user.find().exec(async (err, user) => { if (err) ret ...

Encountering difficulties in generating a new user account on Microsoft through Firebase Authentication

While I successfully integrated Google Auth into my web application, I am encountering difficulties with Microsoft Auth. After following the guidelines provided by Firebase Docs, the redirection process seems to work correctly. However, upon redirecting ba ...

Creating a dynamic web design with HTML and CSS: how to overlay multiple styles of text on

Previously, I inquired about adding text to the gray area of an image. Some experts recommended using <span>, but this resulted in all the text appearing in a single line (as it is inline), even though it was set to display:block. How can I achieve s ...

Retrieving the hidden field value using JavaScript on the server side

I'm encountering an issue with asp:hiddenfield where, after changing its value on the client side and trying to retrieve it on the server side, it returns null. Here is my client-side code: function pageLoad() { var gV = $('#<%=Hidden ...

Issues with Angular ng-click event activation on dialog box button

I have encountered an issue while creating a dialog pop up on my website. When I click a button that is meant to trigger an event and close the dialog, the dialog fails to close. Here is the JavaScript code for the button... $scope.alert = function () { ...

Retrieve the most recent version of the document stored in MongoDB

Is there a way to retrieve the _id (the Mongo ObjectID) of an updated document without having to find it by newData/oldData? I attempted the following: ... collection.update(oldData, newData, function(err, doc) { console.log(docs); // This prints "1" ...

The API Key containing a colon is causing a TypeError when trying to parse it because forEach is not recognized as a function

Trying to utilize the New York Times API to fetch the Top Stories in JSON, I am encountering an issue: Uncaught TypeError: top.forEach is not a function Suspecting that the problem lies with the API key containing colons in the URL, I attempted encoding ...

Step-by-step guide on achieving a radiant glow effect using React Native

I am looking to add a glowing animation effect to both my button and image elements in React Native. Is there a specific animation technique or library that can help achieve this effect? While I have this CSS style for the glow effect, I am uncertain if ...

Angular2 allows users to move text by dragging it with the cursor while holding down the mouse button

Is it feasible to implement a feature in Angular 2 where users can drag text along with the cursor while clicking the mouse? I am currently working on a web "painter" application and would like the ability for users to click on a textbox and move it around ...

Navigating through JQuery

Is there a way to scroll to a div + 100px specifically on the y axis? I am unsure how to achieve this. Can you provide guidance? I attempted using $.scrollTo('div100' + '100px', 2000) but unfortunately, it did not produce the desired ...

Add hover effects to components inside MuiButton

I'm currently working with styled components and Material UI, but I'm struggling to add hover styles to the children of MuiButton. Despite following online resources and documentation, I can't seem to make it work. Here's how my jsx is ...

I'm facing a challenge with retrieving the controller's scope in my Angular directive

Having trouble accessing the settings I receive from the server in my app. The directives are set up correctly and the $http is used to fetch a js file with the app settings. However, despite being able to log the scope in the console, I am unable to acces ...

Extending the Angular Date filter with translation capabilities

During the development of an application that allows users to select a date, I encountered an issue with the translations of the date filter. To resolve this, I implemented the following solution: Extended the date filter functionality Substituted the ...

Using JavaScript to ensure that a div is not hidden on page load if a checkbox is unchecked

Upon inspecting a page, I am implementing a script to check if a checkbox is selected. If not selected, the goal is to hide a specific div element. While troubleshooting this issue, I suspect the problem may be due to the lack of an inline element within t ...

React Component Throws Error: Thunk Fetch is Not Defined

While experimenting with a Thunk function triggered by a form submit, I encountered an issue where the fetch call inside the component was returning undefined and not triggering the .then() method. It's puzzling because I simplified the Thunk function ...

Display a login/logout button on the navbar of an AngularJS app page based on certain conditions

Welcome.jsp <html> <body ng-app="myApp"> <div class="menu"> <a href="/home"> Home </a> <a href="/orders" ng-show="$scope.isUserLoggedIn"> View Orders </label> <a href="/logout" ng-show="$scope.isUserL ...

From dividing into three sections to splitting into two sections

Struggling to create a list of images and descriptions in sets of threes at larger widths, transitioning to twos at smaller widths? The breakdown is causing chaos. Need help achieving clean one-half columns. Appreciate any assistance! ...