Adjust the canvas size to perfectly fit within the parent bootstrap cell in a grid layout

I am currently in the process of creating a dashboard using the Bootstrap grid. Some of the cells contain a canvas element, and I am trying to ensure that it matches the size of its parent. My approach involves the following calculations:

var parent = canvas.parentElement;
if (parent.style) {
  var parentStyle = window.getComputedStyle(parent, null);

  var w = parseFloat(parentStyle.width) - (parseFloat(parentStyle.paddingLeft) + parseFloat(parentStyle.paddingRight) + parseFloat(parentStyle.borderLeftWidth) + parseFloat(parentStyle.borderRightWidth));
  var h = parseFloat(parentStyle.height) - (parseFloat(parentStyle.paddingTop) + parseFloat(parentStyle.paddingBottom) + parseFloat(parentStyle.borderTopWidth) + parseFloat(parentStyle.borderBottomWidth));

  canvas.width = w;
  canvas.height = h;
}

Despite implementing this, the canvas, or the cell, seems to keep increasing in height when I resize the page, and I am puzzled by this behavior.

For a demonstration, run the following example in full page and resize the window horizontally to see how the cells continue to grow in height.

function resizeCanvas(canvas) {
  var parent = canvas.parentElement;
  if (parent.style) {
    var parentStyle = window.getComputedStyle(parent, null);

    var w = parseFloat(parentStyle.width) - (parseFloat(parentStyle.paddingLeft) + parseFloat(parentStyle.paddingRight) + parseFloat(parentStyle.borderLeftWidth) + parseFloat(parentStyle.borderRightWidth));
    var h = parseFloat(parentStyle.height) - (parseFloat(parentStyle.paddingTop) + parseFloat(parentStyle.paddingBottom) + parseFloat(parentStyle.borderTopWidth) + parseFloat(parentStyle.borderBottomWidth));

    canvas.width = w;
    canvas.height = h;
  }
}

function paintOnCanvas(canvas) {
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#FF0000";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.font = "20px Verdana";
  ctx.fillStyle = "black";
  ctx.fillText("Paint on Canvas", 10, 50);
}

document.addEventListener("DOMContentLoaded", function(event) {
  paintOnCanvas(document.getElementById("canvas"));
});

window.addEventListener('resize', function(event) {
  resizeCanvas(document.getElementById("canvas"));
  paintOnCanvas(document.getElementById("canvas"));
});
canvas {
  background-color: #ce8483;
  width: 100%;
  height: 100%;
}

.col-sm-6 {
  border: 1px #2e6da4 solid;
  padding: 15px 15px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">

<div class="container-fluid">
  <div class="row">
    <div class="col-md-4 col-sm-6 col-xs-12">
    </div>
    <div class="col-md-4 col-sm-6 col-xs-12">
      <canvas id="canvas"></canvas>
    </div>
    <div class="col-md-4 col-sm-6 col-xs-12">
    </div>
  </div>
</div>

Answer №1

If you want to get the actual width and height of an HTML element, you should utilize the .offsetWidth and .offsetHeight properties. Remember, these properties are specific to the element itself, not the .style. property.

Resource: How do I retrieve an HTML element's actual width and height?

To ensure the canvas has a minimum height, I included a div with a minimal size. If you remove this div, you can observe the impact on the canvas.

function resizeCanvas(canvas) {
  var parent = canvas.parentElement;
  
  canvas.width = parent.offsetWidth;
  canvas.height = parent.offsetHeight;
}

function paintOnCanvas(canvas) {
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#FF0000";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.font = "20px Verdana";
  ctx.fillStyle = "black";
  ctx.fillText("Paint on Canvas", 10, 50);
}

document.addEventListener("DOMContentLoaded", function(event) {
  resizeCanvas(document.getElementById("canvas"));
  paintOnCanvas(document.getElementById("canvas"));
});

window.addEventListener('resize', function(event) {
  resizeCanvas(document.getElementById("canvas"));
  paintOnCanvas(document.getElementById("canvas"));
});
canvas {
  position:absolute;
  left: 0;
  top: 0;
}

.col-sm-6 {
  border: 1px #2e6da4 solid;
  padding: 15px 15px;
  height: 200px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">

<div class="container-fluid">
  <div class="row">
    <div class="col-md-4 col-sm-6 col-xs-12">
    </div>
    <div class="col-md-4 col-sm-6 col-xs-12">
      <canvas id="canvas"></canvas>
    </div>
    <div class="col-md-4 col-sm-6 col-xs-12">
    </div>
  </div>
</div>

EDIT:
I noticed a mistake in the .col-sm-6 CSS class.
height: 200px; was missing a :.

With this correction, the additional div is no longer necessary.

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

Hide specific content while displaying a certain element

Creating three buttons, each of which hides all content divs and displays a specific one when clicked. For instance, clicking the second button will only show the content from the second div. function toggleContent(id) { var elements = document.getEl ...

When converting to a React Functional Component using Typescript, an error occurred: The property 'forceUpdateHandler' could not be found on the type 'MutableRefObject<Spinner | null>'

Looking to convert the App component in this CodePen into a Functional component using Typescript. Encountering an error when attempting to run it: ERROR in src/App.tsx:13:14 TS2339: Property 'forceUpdateHandler' does not exist on type 'Mu ...

AngularJS directive for automatically resizing Dygraph on page load

Could someone please assist me with resizing my graph inside tabs using Angular? When I initially load the graphs, they don't display unless I manually resize the window. How can I ensure that the graphs are loaded and fill the div on the first load? ...

Arranging elements using the ng-repeat directive in AngularJS

My question pertains to an array I am working with: $scope.answers=["","","",""] This array contains several empty elements. <li ng-repeat="item in answers "><input type="text" ng-model="item"/></li> When running this code, an error i ...

Removing a Request with specified parameters in MongoDB using NodeJS

Working with Angular 4 and MongoDB, I encountered an issue while attempting to send a delete request. My goal was to delete multiple items based on their IDs using the following setup: deleteData(id) { return this.http.delete(this.api, id) } In order ...

The data from my client side AJAX request is not being received by my server side PHP script

Check out the AJAX code I've written: $("#loginbutton").click(function(){ var email = $('#email').val(); var password = $('#password').val(); $.ajax({ url: 'login.php& ...

Guide on integrating a JavaScript control (JavaScript package) obtained from GitHub into my asp.net application

Hello everyone, I am a newcomer to GitHub and have some basic questions to ask. Recently, I downloaded the package from https://github.com/jspreadsheet/ce in .zip format for using in my asp.net web application. However, I am not sure how to incorporate the ...

What causes Vue to only update once when there are two closely timed mutations to reactive data?

Can you take a look at this simple example? export default { data() { return { name: "Amy", age: 18, }; }, computed: { combinedDataForWatching() { return { name: this.name, age: this.age, ...

Ways to stop the react-router from causing the page to refresh

Need assistance with React Router issue I'm working on a project in reactJs using react-router-dom v5. I have set up a default route for routing. <Redirect to={"someComponent"}/> The problem is that when I refresh the page, it auto ...

What is the best way to align a button with a title on the right side of a page?

Is it possible to align my button to the top right, at the same height as the title in my design? Here is an example: view image here This is what I have achieved so far: view image here I suspect there may be an issue with my divs. The button doesn&a ...

Having trouble initializing a variable in a function and accessing it from a separate function

Currently, I am executing a node js file which is receiving a post request as shown below. app.post('/', function (req, res) { var firstLine = req.body.firstLine; var secondLine = req.body.secondLine; var previewID = req.body.preview ...

Error: The module you are trying to import from the package is not found. Please check the package path and make sure that

I encountered an issue when trying to compile a code in Reactjs. As a beginner in Reactjs, I'm struggling with this. Module not found: Error: Package path ./cjs/react.development is not exported from package /Users/mansi/letsgrowmore/to-do-list/my-rea ...

Attempting to eliminate redundant data retrieved from an XML file being presented on my webpage

I need help deleting duplicate artists that appear when retrieving information from an XML file using JQuery. How can I achieve this? Check out the JS file below: $(function(){ $(window).load(function(){ $.ajax({ url: 'http://imagination ...

What is the best way to replicate a synchronous ajax call? (mimicking synchronous behavior with asynchronous methods)

Given that a "native" synchronous ajax call can block the user interface of the browser, it may not be suitable for many real-world scenarios (including mine). I am curious to know if there is a way to mimic a synchronous (blocking) ajax call using an asy ...

Properties that cannot be modified, known as read-only properties,

While browsing through this post on read-only properties, I stumbled upon the following code snippet: var myObject = { get readOnlyProperty() { return 42; } }; alert(myObject.readOnlyProperty); // 42 myObject.readOnlyProperty = 5; // Assignment al ...

delivering axios response to display the page

I have a code snippet that requests data from an external API using axios and I want to incorporate the response into my rendered page. Here is my code: //Snippet from my controller required in main routes exports.recordBySlug = async (req, res, next) =&g ...

Why does the custom method only trigger once with the addEventListener?

I am attempting to connect the "oninput" event of an input range element to a custom method defined in a corresponding typescript file. Here is the HTML element: <input type="range" id='motivation-grade' value="3" min="1" max="5"> This i ...

Having difficulty invoking a JavaScript function at a global level

Currently, I am working on a nodejs application that involves mongoDB integration. In my code, I have created a function to extract specific data from MongoDB and save it in a variable called "docs". Despite multiple attempts to declare the function global ...

Transmitting extensions via AJAX

I am having trouble sending navigator plugins with AJAX as I am only getting one plugin in the result. The plugin list currently shows: Shockwave Flash. However, it should display like this: Shockwave Flash - Chrome Remote Desktop Viewer - Native Client.. ...

Once more, objects cannot be used as a child element in React

I understand that there are similar questions about this topic, but I am struggling to approach it in a different way. I really need an array of objects to be inside a map. I have created an array to map it, but I need to find different information to disp ...