How to make canvas responsive - css
I use bootstrap. I want the user to be able to choose the canvas size while keeping the design screen responsive within the div.
<div class="row">
<div class="col-xs-2 col-sm-2" id="border">content left</div>
<div class="col-xs-6 col-sm-6" id="border">
Width <input type="number" class="form-control"><br>
Height <input type="number" class="form-control"><br>
canvas
<canvas id="canvas" width="500" height="300">
</canvas>
</div>
<div class="col-xs-2 col-sm-2" id="border">content right</div>
How can I limit the size of the canvas to the size of the div?
I do not know if it will be necessary to use JavaScript.
Edit
It should be taken into account that the width and height values are entered by the user and the canvas must be in div proportional in size
https://jsfiddle.net/1a11p3ng/2/
You can have a responsive canvas in 3 short and simple steps:
Remove the width and height attributes from your <canvas>.
<canvas id="responsive-canvas"></canvas>
Using CSS, set the width of your canvas to 100%.
#responsive-canvas {
width: 100%;
}
Using JavaScript, set the height to some ratio of the width.
var canvas = document.getElementById('responsive-canvas');
var heightRatio = 1.5;
canvas.height = canvas.width * heightRatio;
To change width is not that hard. Just remove the width attribute from the tag and add width: 100%; in the css for #canvas
#canvas{
border: solid 1px blue;
width: 100%;
}
Changing height is a bit harder: you need javascript. I have used jQuery because i'm more comfortable with.
you need to remove the height attribute from the canvas tag and add this script:
<script>
function resize(){
$("#canvas").outerHeight($(window).height()-$("#canvas").offset().top- Math.abs($("#canvas").outerHeight(true) - $("#canvas").outerHeight()));
}
$(document).ready(function(){
resize();
$(window).on("resize", function(){
resize();
});
});
</script>
You can see this fiddle: https://jsfiddle.net/1a11p3ng/3/
EDIT:
To answer your second question. You need javascript
0) First of all i changed your #border id into a class since ids must be unique for an element inside an html page (you can't have 2 tags with the same id)
.border{
border: solid 1px black;
}
#canvas{
border: solid 1px blue;
width: 100%;
}
1) Changed your HTML to add ids where needed, two inputs and a button to set the values
<div class="row">
<div class="col-xs-2 col-sm-2 border">content left</div>
<div class="col-xs-6 col-sm-6 border" id="main-content">
<div class="row">
<div class="col-xs-6">
Width <input id="w-input" type="number" class="form-control">
</div>
<div class="col-xs-6">
Height <input id="h-input" type="number" class="form-control">
</div>
<div class="col-xs-12 text-right" style="padding: 3px;">
<button id="set-size" class="btn btn-primary">Set</button>
</div>
</div>
canvas
<canvas id="canvas"></canvas>
</div>
<div class="col-xs-2 col-sm-2 border">content right</div>
</div>
2) Set the canvas height and width so that it fits inside the container
$("#canvas").outerHeight($(window).height()-$("#canvas").offset().top-Math.abs( $("#canvas").outerHeight(true) - $("#canvas").outerHeight()));
3) Set the values of the width and height forms
$("#h-input").val($("#canvas").outerHeight());
$("#w-input").val($("#canvas").outerWidth());
4) Finally, whenever you click on the button you set the canvas width and height to the values set. If the width value is bigger than the container's width then it will resize the canvas to the container's width instead (otherwise it will break your layout)
$("#set-size").click(function(){
$("#canvas").outerHeight($("#h-input").val());
$("#canvas").outerWidth(Math.min($("#w-input").val(), $("#main-content").width()));
});
See a full example here https://jsfiddle.net/1a11p3ng/7/
UPDATE 2:
To have full control over the width you can use this:
<div class="container-fluid">
<div class="row">
<div class="col-xs-2 border">content left</div>
<div class="col-xs-8 border" id="main-content">
<div class="row">
<div class="col-xs-6">
Width <input id="w-input" type="number" class="form-control">
</div>
<div class="col-xs-6">
Height <input id="h-input" type="number" class="form-control">
</div>
<div class="col-xs-12 text-right" style="padding: 3px;">
<button id="set-size" class="btn btn-primary">Set</button>
</div>
</div>
canvas
<canvas id="canvas">
</canvas>
</div>
<div class="col-xs-2 border">content right</div>
</div>
</div>
<script>
$(document).ready(function(){
$("#canvas").outerHeight($(window).height()-$("#canvas").offset().top-Math.abs( $("#canvas").outerHeight(true) - $("#canvas").outerHeight()));
$("#h-input").val($("#canvas").outerHeight());
$("#w-input").val($("#canvas").outerWidth());
$("#set-size").click(function(){
$("#canvas").outerHeight($("#h-input").val());
$("#main-content").width($("#w-input").val());
$("#canvas").outerWidth($("#main-content").width());
});
});
</script>
https://jsfiddle.net/1a11p3ng/8/
the content left and content right columns will move above and belove the central div if the width is too high, but this can't be helped if you are using bootstrap. This is not, however, what responsive means. a truly responsive site will adapt its size to the user screen to keep the layout as you have intended without any external input, letting the user set any size which may break your layout does not mean making a responsive site.
The object-fit CSS property sets how the content of a replaced element, such as an img or video, should be resized to fit its container.
Magically, object fit also works on a canvas element. No JavaScript needed, and the canvas doesn't stretch, automatically fills to proportion.
canvas {
width: 100%;
object-fit: contain;
}
<div class="outer">
<canvas id="canvas"></canvas>
</div>
.outer {
position: relative;
width: 100%;
padding-bottom: 100%;
}
#canvas {
position: absolute;
width: 100%;
height: 100%;
}
extending accepted answer with jquery
what if you want to add more canvas?, this jquery.each answer it
responsiveCanvas(); //first init
$(window).resize(function(){
responsiveCanvas(); //every resizing
stage.update(); //update the canvas, stage is object of easeljs
});
function responsiveCanvas(target){
$(canvas).each(function(e){
var parentWidth = $(this).parent().outerWidth();
var parentHeight = $(this).parent().outerHeight();
$(this).attr('width', parentWidth);
$(this).attr('height', parentHeight);
console.log(parentWidth);
})
}
it will do all the job for you
why we dont set the width or the height via css or style? because it will stretch your canvas instead of make it into expecting size
this seems to be working :
#canvas{
border: solid 1px blue;
width:100%;
}
One of the best possible way to do this without even using JavaScript is to just put that canvas inside a div tag and then display block (Note: width:100%; height:100%; is completely optional).
Run the snippet below to see how it works.....
.container {
display: block;
margin: auto;
height: auto;
}
#canvas {
width: 100%;
height: 100%;
border: 1px solid black;
}
<div class="container">
<!-- width and height are set just to show you it actually works-->
<canvas id="canvas" width=864 height=480></canvas>
</div>
There's a better way to do this in modern browsers using the vh and vw units.
vh is the viewport height.
So you can try something like this:
<style>
canvas {
border: solid 2px purple;
background-color: green;
width: 100%;
height: 80vh;
}
</style>
This will distort the aspect ration.
You can keep the aspect ratio by using the same unit for each. Here's an example with a 2:1 aspect ratio:
<style>
canvas {
width: 40vh;
height: 80vh;
}
</style>
try using max-width: 100%; on your canvas.
canvas {
max-width: 100%;
}
Hi I know this post has been going on for a while, but I had a very similar problem with my canvas. like mentioned as the viewport gets resized and so does the elements within the window. This can be done using css, however it doesnt quite apply to the elements within the canvas. Now if your canvas context is 2D this is the solution that works for me...
This can be used as a method.
class ParentObject{
constructor()
/**
* #this this._width - Private width variable that would store the size of the window width
*/
this._width = Number();
/**
* #this this._height - Private Height variable that would store the height of the window
*/
this._height= Number();
/**
* Calls the getCanvasDimensions method
*/
this.getCanvasDimensions();
//Getting the Width and Height as soon as the Window loads
window.addEventListener('load',()=>{
this.getCanvasDimensions()
})
//As the window is resized we are getting the new Canvas Dimensions
window.addEventListener('resize',()=>{
this.getCanvasDimensions();
getCanvasDimensions() {
// Width is determined by the css value for the viewport width this is then respected by the device pixel ratio. This is then used to set the canvas.width value
this._width = Math.round((Number(getComputedStyle(canvas).getPropertyValue('width').slice(0,-2))/devicePixelRatio) * devicePixelRatio);
//Setting the canvas width
canvas.width = this._width
// height is determined by the css value for the viewport height this is then respected by the device pixel ratio. This is then used to set the canvas.height value
this._height = Math.round((Number(getComputedStyle(canvas).getPropertyValue('height').slice(0,-2))/devicePixelRatio) * devicePixelRatio);
//Setting the canvas height
canvas.height = this._height
}
get width(){
//This sets the width to the private _width value
return this._width
}
get height(){
//This sets the height to the private _height value
return this._height
}
As a function on the global scope:
let width,height
function responsiveCanvas(){
let w = Math.round((Number(getComputedStyle(canvas).getPropertyValue('width').slice(0,-2))/devicePixelRatio) * devicePixelRatio);
width = canvas.height = w;
let h = Math.round((Number(getComputedStyle(canvas).getPropertyValue('height').slice(0,-2))/devicePixelRatio) * devicePixelRatio);
height = canvas.height = h;
}
window.addEventListener('load',responsiveCanvas)
window.addEventListener('resize',responsiveCanvas)
Then just use the width and height variables to reference the sizes.
Anyways I hope that this helps someone out.
Try changing the width of the canvas to be equal to it's parent element.
<template>
<span class="Wrapper">
<canvas id="myChart" ></canvas>
</span>
</template>
<script>
const ctx = document.getElementById('myChart');
ctx.width = ctx.parentElement.offsetWidth;
ctx.height = ctx.parentElement.offsetHeight;
</script>
Related
Scale images of different size using Bootstrap/CSS
I have a web application layout like this, styled with Bootstrap: ------------------------ | Header | ------------------------ | Display Area | ------------------------ The Header is a collection of control elements (mostly buttons) and therefore almost of same height. The Display Area contains the following: <div class="row"> <div class="col"> <img class="img-fluid" src="http://localhost/api/currentImage" /> </div> </div> http://localhost/api/currentImage returns an image. The image's size always differs: sometimes the width is bigger than height, sometimes vice versa. Now I'd like to scale the image in that way that it uses as much as possible of the available Display without "overflowing". By overflowing, I mean that there is never a need to show a horizontal or vertical scroll bar because the image is too wide or too high. Right now, <img class="img-fluid" ... only scales the width correctly. How can I achieve this using Bootstrap/CSS?
Bootstrap will let you resize images with its img-fluid class, but if you need to make the image cover the entire space you would have to write your own CSS, you could make use of the object-fit property to set the image to fill the container, while maintaining its aspect ratio and clipping off if necessary; As you can see in the example below, the image is narrow, but it will fill the entire container even if it has to expand to do so. EDIT: Included two more examples with fill and contain so you can see how their behavior changes. header { border: 1px solid red; padding: 10px; } section { border: 1px solid blue; } img { height: calc(100vh - 20px); width: 100%; /* This is just to remove a blank space at the bottom of the image */ display: block; } img.cover { object-fit: cover; } img.contain { object-fit: contain; } img.fill { object-fit: fill; } <header> This is a header </header> <section> <img class="cover" src="https://via.placeholder.com/200x700" /> </section> <section> <img class="contain" src="https://via.placeholder.com/200x700" /> </section> <section> <img class="fill" src="https://via.placeholder.com/200x700" /> </section>
Bootstrap has a predefined classes for responsive image. Check the following class, .img-responsive Makes an image responsive (will scale nicely to the parent element) <div class="row"> <div class="col"> <img class="img-fluid img-responsive" src="http://localhost/api/currentImage" /> </div> </div> `
angular - click flexbox grid cell to expand area below with full width
I have something like calendar grid using flexbox inside a ionic 3 project. The cells are one array <div class="sb-calendar-wrapper"> <div class="sb-calendar-month"> <div class="sb-calendar-row"> <div class="sb-calendar-cell sb-cell-labels sb-week-day" *ngFor="let day of sbcalendar.dayLabels"> {{day}} </div> </div> <div class="sb-calendar-row"> <div class="sb-calendar-cell sb-cell" *ngFor="let day of calendarDays, let j=index" (click)="openCalendarDay(day)" [ngStyle]="{'height': (day.isOpen) ? '300px' : '60px'}">{{j}} </div> </div> </div> </div> .sb-cell { position: relative; border-bottom: 1px solid rgba(130, 171, 183, 0.2); padding: 5px; height: calc((100vh - 150px)/6); .sb-calendar-day-list{ position: absolute; width: 100vw; left: 0; top:calc((100vh - 150px)/6); background: #ccc; height: calc( 300px - calc((100vh - 150px)/6)); } } When I click on any day, i want the "row" to expand to display an area which I can use for e.g. displaying items of that cell. The problem I'm facing is how to position that list element, so that i will fill the entire space or width. With position:relative of the cell I can position everything fine except for the left:0, which doesnt work for most cells. In summary when i click any day, a box that fills the entire view width should expand. thanks for any suggestions! EDIT1 I don't want to create manual rows after each n-cell. The cell array should stay as a single array while the flexitem widths controls how many items are in each row.
I think you can organize those days on the same line as a row. At the end of each row, you can add a place holder div with an ng-if condition. Whenever you click on a day of that row, you can check the row index for showing the div or not. That div will hold an area that you want. html: <div class="flexbox-row" ng-repeat="row in rows track by $index"> <div class="flexbox-col clickable" ng-click="showRow($index)"> 1 </div> <div class="flexbox-col clickable" ng-click="showRow($index)"> 2 </div> <div class="flexbox-col clickable" ng-click="showRow($index)"> 3... </div> <!-- Place holder div --> <div ng-if="showRow() === $index"> <div data-custom-directive></div> </div> </div> Show row code: scope.showRow = function ($index) { // Return activeRow if ($index === undefined) { return scope.activeRow; } // Hide if same row if ($index === scope.activeFlight) { scope.activeRow = null; return; } // Show row scope.activeRow = parseInt($index); };
Image responsive in bootstrap to fill column
I have a bootstrap column defined as follows: <div class="col-md-4 limit"> <img id="myImage" src="" class="img-responsive"/> </div> <style> .limit { max-height:500px; overflow:hidden; } </style> The source of the image is obtained programatically so I do not know in advance the height or width of my image. What I want to do is that the image in this column whose height is limited appear completely inside of the div. With the img-responsive class I have achieved the image to horizontally fill my column, however, as this class also sets the height to auto, most of the time this causes the image to overflow and be hidden. I do not want my image to overflow in any way. So, lets say that my column measures: Width: 300px (defined by bootstrap) Height: 500px (.limit) And my image dimensions are: Width: 600px Height: 1500px The current configuration makes the image shrink to 300px x 750px. As its container is set to only 500px, this causes the last 250px to be lost inside the overflow. I would like to image instead to be resized to 200px x 500px in order for it to completely into the containing div How can I do this? Thanks!
Try this: <div class="row"> <div class="col-md-4"> <div class="limit"> <img src="images/yourimage.png" alt="" /> </div> </div> </div> <style type="text/css"> .limit{ width: 300px; height: 500px; max-height: 500px; overflow: hidden; } .limit img{ width: 100%; height: 100%; } </style>
You could try to inherit the height or the width of the parent div (as both would not contain proportions). This could only work if you have the same type of img (all portret or landscape). Other solution is to calculate the dimensions based on the max width/height of the img in your program language. Pick the one that matches the condition (both var <= max value). Then echo the solution in your html.
#Luis Becerril I normally used this plugin with those type of issues. Please try this. If may suit to your requirement. jQuery Image Center
Simplest way in Bootstrap 4 <div class="row"> <div class="col-md-4"> <img src="images/yourimage.png" alt="" class="w-100" /> </div> </div>
Image not loading in chrome from css background property
I am using "background: #BDBDBD url(image.png) top left no-repeat" this css property for two div elements which has width and height set. On clicking a button I am changing the width of both the nested divs dynamically by making the function run continuously with the help of setInterval(). The image is not loading in chrome but it works fine in firefox and IE .. Many searches convey that using background image in chrome is not working but none of those solutions seems to work. <div id="boxes"> <div id="dialog" class="window" style="overflow: auto"> <div id="progressBar" class="meter-wrap" style="display: block;position: relative; margin: auto;"> <div class="meter-value" style="background-color: #05C; width: 40%"> <div class="meter-text"> Loading... </div> </div> </div> <div class="meter-text-message"> Loading... </div> </div> CSS: .meter-wrap, .meter-value, .meter-text { width: 155px; height: 30px; } .meter-wrap, .meter-value { background: #bdbdbd url('/sf-images/tracker/inline_progress_bar.png') top left no-repeat; } js code: function setProgressBar() { var pgBar = jQuery("#progressBar"); pgBar.show(); running = true; var inter = null; function run() { pgBar.find(".meter-value").css("width", progress + "%"); pgBar.find(".meter-text").text(progress + "%"); if (progress == 100) { jQuery(".meter-text-message").html("Complete"); clearInterval(inter); running = false; } } inter = setInterval(run, 50); } Found that the image is not loading for first time, I made the div element visible with the image as background by another method. After that , when I execute the above js method image loads properly.
Bootstrap Element 100% Width
I want to create alternating 100% colored blocks. An "ideal" situation is illustrated as an attachment, as well as the current situation. Desired setup: Currently: My first idea was to create an div class, give it a background color, and give it 100% width. .block { width: 100%; background: #fff; } However, you can see that this obviously doesn't work. It's confined to a container area. I tried to close the container and that didn't work either.
The container class is intentionally not 100% width. It is different fixed widths depending on the width of the viewport. If you want to work with the full width of the screen, use .container-fluid: Bootstrap 3: <body> <div class="container-fluid"> <div class="row"> <div class="col-lg-6"></div> <div class="col-lg-6"></div> </div> <div class="row"> <div class="col-lg-8"></div> <div class="col-lg-4"></div> </div> <div class="row"> <div class="col-lg-12"></div> </div> </div> </body> Bootstrap 2: <body> <div class="row"> <div class="span6"></div> <div class="span6"></div> </div> <div class="row"> <div class="span8"></div> <div class="span4"></div> </div> <div class="row"> <div class="span12"></div> </div> </body>
QUICK ANSWER Use multiple NOT NESTED .containers Wrap those .containers you want to have a full-width background in a div Add a CSS background to the wrapping div Fiddles: Simple: https://jsfiddle.net/vLhc35k4/ , Container borders: https://jsfiddle.net/vLhc35k4/1/ HTML: <div class="container"> <h2>Section 1</h2> </div> <div class="specialBackground"> <div class="container"> <h2>Section 2</h2> </div> </div> CSS: .specialBackground{ background-color: gold; /*replace with own background settings*/ } FURTHER INFO DON'T USE NESTED CONTAINERS Many people will (wrongly) suggest, that you should use nested containers. Well, you should NOT. They are not ment to be nested. (See to "Containers" section in the docs) HOW IT WORKS div is a block element, which by default spans to the full width of a document body - there is the full-width feature. It also has a height of it's content (if you don't specify otherwise). The bootstrap containers are not required to be direct children of a body, they are just containers with some padding and possibly some screen-width-variable fixed widths. If a basic grid .container has some fixed width it is also auto-centered horizontally. So there is no difference whether you put it as a: Direct child of a body Direct child of a basic div that is a direct child of a body. By "basic" div I mean div that does not have a CSS altering his border, padding, dimensions, position or content size. Really just a HTML element with display: block; CSS and possibly background. But of course setting vertical-like CSS (height, padding-top, ...) should not break the bootstrap grid :-) Bootstrap itself is using the same approach ...All over it's own website and in it's "JUMBOTRON" example: http://getbootstrap.com/examples/jumbotron/
This is how you can achieve your desired setup with Bootstrap 3: <div class="container-fluid"> <div class="row"> <!-- Give this div your desired background color --> <div class="container"> <div class="row"> <div class="col-md-12"> ... your content here ... </div> </div> </div> </div> </div> The container-fluid part makes sure that you can change the background over the full width. The container part makes sure that your content is still wrapped in a fixed width. This approach works, but personally I don't like all the nesting. However, I haven't found a better solution so far.
There is a workaround using vw. Is useful when you can't create a new fluid container. This, inside a classic 'container' div will be full size. .row-full{ width: 100vw; position: relative; margin-left: -50vw; left: 50%; } After this there is the sidebar problem (thanks to #Typhlosaurus), solved with this js function, calling it on document load and resize: function full_row_resize(){ var body_width = $('body').width(); $('.row-full').css('width', (body_width)); $('.row-full').css('margin-left', ('-'+(body_width/2)+'px')); return false; }
In bootstrap 4, you can use 'w-100' class (w as width, and 100 as 100%) You can find documentation here: https://getbootstrap.com/docs/4.0/utilities/sizing/
If you can't change the HTML layout: .full-width { width: 100vw; margin-left: -50vw; left: 50%; } <div class="container"> <div class="row"> <div class="col-xs-12">a</div> <div class="col-xs-12">b</div> <div class="col-xs-12 full-width">c</div> <div class="col-xs-12">d</div> </div> </div> Demo: http://www.bootply.com/tVkNyWJxA6
Sometimes it's not possible to close the content container. The solution we are using is a bit different but prevent a overflow because of the firefox scrollbar size! .full-width { margin-top: 15px; margin-bottom: 15px; position: relative; width: calc(100vw - 10px); margin-left: calc(-50vw + 5px); left: 50%; } Here is a example: https://jsfiddle.net/RubbelDeKatz/wvt9253q
Instead of style="width:100%" try using class="col-xs-12" it will save you 1 character :)
Sorry, should have asked for your css as well. As is, basically what you need to look at is giving your container div the style .container { width: 100%; } in your css and then the enclosed divs will inherit this as long as you don't give them their own width. You were also missing a few closing tags, and the </center> closes a <center> without it ever being open, at least in this section of code. I wasn't sure if you wanted the image in the same div that contains your content or separate, so I created two examples. I changed the width of the img to 100px simply because jsfiddle offers a small viewing area. Let me know if it's not what you're looking for. content and image separate: http://jsfiddle.net/QvqKS/2/ content and image in same div (img floated left): http://jsfiddle.net/QvqKS/3/
I would use two separate 'container' div as below: <div class="container"> /* normal*/ </div> <div class="container-fluid"> /*full width container*/ </div> Bare in mind that container-fluid does not follow your breakpoints and it is a full width container.
I'd wonder why someone would try to "override" the container width, since its purpose is to keep its content with some padding, but I had a similar situation (that's why I wanted to share my solution, even though there're answers). In my situation, I wanted to have all content (of all pages) rendered inside a container, so this was the piece of code from my _Layout.cshtml: <div id="body"> #RenderSection("featured", required: false) <section class="content-wrapper main-content clear-fix"> <div class="container"> #RenderBody() </div> </section> </div> In my Home Index page, I had a background header image I'd like to fill the whole screen width, so the solution was to make the Index.cshtml like this: #section featured { <!-- This content will be rendered outside the "container div" --> <div class="intro-header"> <div class="container">SOME CONTENT WITH A NICE BACKGROUND</div> </div> } <!-- The content below will be rendered INSIDE the "container div" --> <div class="content-section-b"> <div class="container"> <div class="row"> MORE CONTENT </div> </div> </div> I think this is better than trying to make workarounds, since sections are made with the purpose of allowing (or forcing) views to dynamically replace some content in the layout.
Though people have mentioned that you will need to use .container-fluid in this case but you will also have to remove the padding from bootstrap.
The following answer is not exactly optimal by any measure, but I needed something that maintains its position within the container whilst it stretches the inner div fully. https://jsfiddle.net/fah5axm5/ $(function() { $(window).on('load resize', ppaFullWidth); function ppaFullWidth() { var $elements = $('[data-ppa-full-width="true"]'); $.each( $elements, function( key, item ) { var $el = $(this); var $container = $el.closest('.container'); var margin = parseInt($container.css('margin-left'), 10); var padding = parseInt($container.css('padding-left'), 10) var offset = margin + padding; $el.css({ position: "relative", left: -offset, "box-sizing": "border-box", width: $(window).width(), "padding-left": offset + "px", "padding-right": offset + "px" }); }); } });
This must work (Mobile phone as well as Desktop screen): class: alignfull and class: img-fluid will do the magic. <div class="alignfull"> <img class="img-fluid" style="background-size: cover; background-position: center ; background-repeat: no-repeat; height: auto; min-width: 100%; width: -moz-available; " src="{{ $image->image }}" alt="An image"> </div>