MPDF document and Image DPI problems - php

Background:
I am trying to render a business card at 300dpi using the mPDF library. The document has an image background which should fill the canvas and then have various text elements overlayed.
Dimensions:
The PDF document is set to 91mm x 61mm and is in Landscape format.
$pdf = new mPDF('utf-8', array(91,61), 0, '', 0, 0, 0, 0, 0, 'L');
I have the resolution set in the config as follows;
$this->dpi = 300;
$this->img_dpi = 300
I have create an image in photoshop, also at 300dpi to the same dimensions as the card (91mm x 61mm).
I have tried adding the image to the document inside a div using markup as follows:
$html .= '<div style="position: absolute; left:0; right: 0; top: 0; bottom: 0;width:100%; height:100%"><img style="width:100%; height:100%" src="/assets/images/bg.jpg"></div>';
When the PDF document is displayed, the image seems to be smaller than the document, ie, it is not scaled to fit the page. In fact the image only appears to fill approximately 55-60% of the canvas in X and Y directions.
When I save the PDF document and look at its properties inside Adobe reader it is confirmed to be the correct size of 91x61mm.
Has anyone had a similar problem or understand what is going on here?
I really need to be able to have a 300dpi image which will fill the page exactly.
I look forward to your suggestions.
Regards
James

the css styles you have dont entirely match the ones in the manual's recommendation in the 'size constraint' section
in my case, i have a landscape image that's 11x8.5 inches 150dpi in photoshop, which is matched in mpdf as the page size, i separated the css for cleanliness
just in case, i specified any other mpdf values or css settings
so try something more like this code that is working for me, position the text with css & adjust the dpi/page size as needed:
$html = '
<html>
<head>
<style>
body {
position: relative;
text-align: center;
overflow: hidden;
page-break-inside: avoid;
}
#bg {
position: absolute;
left:0;
right: 0;
top: 0;
bottom: 0;
}
#bg img {
width: 100%;
height: 100%;
margin: 0;
}
#text1 {
top: 20%;
font-size: 20pt;
position: absolute;
width: 100%;
color: #fff;
}
#text2 {
top: 60%;
font-size: 16pt;
position: absolute;
width: 100%;
color: #ddd;
}
</style>
</head>
<body>
<div id="bg">
<img src="bg.png" />
</div>
<div id="text1">John Smith</div>
<div id="text2">555-5555</div>
</body>
</html>';
$mpdf = new mPDF('UTF8','Letter-L',14,'Arial',0,0,0,0,0,0);
$mpdf->dpi = 150;
$mpdf->img_dpi = 150;
$mpdf->WriteHTML($html);
$mpdf->SetDisplayMode('fullpage');
$mpdf->Output();
there is of course an easier way to make a background... tell body or html to have a background image in css, but then you run into this bug so it's not my first recommendation

Related

Div positioning on the screen

I have these two styles that position my div in the footer of my page. What happens is that when you generate the content of the page for php, these div can override the content.
div.panel-foot {
position: absolute;
z-index: 2;
height: 30px;
width: 100%;
bottom: 0;
color: white;
background-color: #333333;
white-space: nowrap;
padding: 5px 100px;
}
div.panel-foot-information {
background-color: rgb(65, 65, 65);
position: absolute;
bottom: 30px;
max-width: none !important;
z-index: 1;
color: white;
font-size: small;
padding-top: 10px;
padding-bottom: 10px;
}
So what I do is when the content is small they stay on radapé ie with position: absolute, and when the content is longer they stay position: relative.
Anyone know a solution to resize content dynamically?
Unlike the other answers so far, I'm going to assume you have images and other things that a real website has, besides text.
I suggest using Javascript (since you've got a jQuery tag). PHP ultimately has no idea how much space the content will take up in the browser, so JS is your best option.
Have a look at my example here. If you remove some of the div content, you will see the footer color changes (because it changes the classname). all you have to do is plug in your own selectors and classnames and you're good to go.
// check the size of your conent div
// assuming it's got an id of "content"
contentHeight = $("#content").height();
// set the threshold that will determine how big is too big
threshold = 300;
// or if you want to make the threshold as big as the window...
// threshold = $(window).height();
// if the content height is greater than the threshold..
if(contentHeight > threshold){
// remove one class and add another
$("#footer").removeClass('green');
$("#footer").addClass('red');
}
// otherwise, do the opposite
else{
$("#footer").removeClass('red');
$("#footer").addClass('green');
}

Positioning in mPDF

I am working on a business card application, where at the final stage you can generate a PDF file from HTML and CSS. What I am trying to achieve is to absolute position the elements on the image within a div, which has relative positioning. All of my elements are draggable on the card.
Here is my PHP file: (note: I shortened the file to be understandable)
<?php
$html = '<div class="card">
<span id="company_card" class="draggable_data">BMW</span>
<img class="bck_icon" src="redtop.jpg" alt="red">
</div>';
include('mpdf/mpdf.php');
$mpdf = new mPDF();
$stylesheet = file_get_contents('test.css'); // external css
$mpdf->WriteHTML($stylesheet,1);
$mpdf->WriteHTML($html, 2);
$mpdf->Output();
The CSS file is the following:
.bck_icon {
border: 1px solid black;
}
.card {
margin: auto;
width: 460px;
height: 260px;
position:relative;
}
#name_card {
position: absolute;
top: 190px;
left:80px;
}
Is there a way to achieve this? I know there are positioning issues in mPDF, but when I do not use the div element, then the elements inside the div will not fit the outside relative element.
Any suggestions?
I encounter similar positioning problems with mPDF. Some of them I solved by using negative margins.
For example, instead of attempting to use position:absolute; you could try to position the name on the card like this:
#name_card {
margin-top: -70px; // more or less
margin-left: 80px;
}
Another option to consider is using background-images: background-image; and background-position' CSS also works in mPDF.

Centered square images in css without set dimensions

I'm trying to make square images from rectangular in css. They also need to be centered.
I've read a lot of questions here, but the answers, good as they might be, always use constant sizes in pixels whereas I need tem to be in percents so the theme can remain responsive.
Basically I need to change this:
into this:
but if the screen is even smaller:
The main problem here is I cannot predict the screen size. It is designed for mobile, so they can vary.
I was thinking about doing css in php (it's for wordpress so it's possible). I was thinking something like width:50% and use the width as a variable, but if I set the height to be equal to width, it will be 50% as well. Is there a way to, I don't know, convert the width to pixels or something? I'm out of ideas, please help.
The problem is, that it is just not possible to change the height relative to the width. So your problem is not the image itself (using overflow: hidden or background-size: cover will do that) but having the square size of your container with dynamic width and then the same height.
A very strange way would be to use a square image (_blank.png with 1px x 1px) and add width: 100% so the height will be the same.
with css:
div{width: 30%;}
img{width: 100%;}
and then add your actual picture as background-image with
background-size: cover;
background-position: center;
Neither performant nor beautiful, but it works.
have you tried this
img { width: 80%; }
make sure there is no height for img in your css file. Also make sure not to set something like height="500px" width="500px" in your html/php file.
also to be centered just do
img { margin: auto; }
Nice picture ;)
If you have an image you want centred—but covers—a parent element, using CSS only, then you’ll need two wrappers:
This works only for wide images. Portrait images will just centre themselves within the container.
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
}
.outer-wrapper {
position: relative;
width: 200px;
height: 200px;
margin: 0 auto;
overflow: hidden;
}
.inner-wrapper {
position: relative;
display: inline-block;
right: -50%;
}
.inner-wrapper img {
display: inline-block;
position: relative;
left: -50%;
}
</style>
</head>
<body>
<div class="outer-wrapper">
<div class="inner-wrapper">
<img src="//placehold.it/400x200" alt="" />
</div>
</div>
</body>
</html>
Just use img{max-width:100% !important; margin:0 auto !important;} and I think it will help you.
Try following css for your image. It won't break the pixels/dimensions for the image.
.imageClass img {
width: 50%;
height: auto;
}
.imageClass img {
width: auto;
height: 50%;
}
<img src="image_path" alt="" class="imageClass" />

How to Auto-Resize a DIV with CSS while keeping Aspect Ratio?

What I have is a standard form in HTML that allows the user to select a "Width" option and a "Height" option (each with values ranging from 1 to 10). When they send the form, it sends it to a PHP/HTML page where PHP grabs the "Width" and "Height" variables and assigns it to a width and height of a DIV.
But what I'm trying to do is just use the "Width" and "Height" variables to assign an aspect ratio to that DIV, and then have that DIV auto-resize to 100% of the container it is inside, but while keeping that same aspect ratio.
Example:
User selects a Width of 4 and a Height of 2, then sends the form. On the receiving PHP page, that DIV (the one receiving the width and height ratios) is inside a container that's 1000px width and 600px height. So now, that DIV resizes to 1000px wide and 500px tall (that would be the aspect ratio of 4 to 2)
Any ideas, codes, scripts would be extremely helpful, thank you very much!
Aaron
Since percentage values of the padding-* properties are calculated with respect to the width of the generated box's containing block, you could:
Add a dummy element with no content but with a percentage in a vertical padding (padding-top or padding-bottom), corresponding to the desired aspect ratio.
Use absolutely positioning to remove all contents from the normal flow of the element, in order to prevent them from increasing the height. Then, make it grow to fill the container.
This idea is taken from http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio
#container {
position: relative;
width: 50%;
}
#dummy {
padding-top: 75%; /* 4:3 aspect ratio */
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver;
}
<div id="container">
<div id="dummy"></div>
<div id="element">
some text
</div>
</div>
Note vertical margin could be used instead of vertical padding, but then there would be margin collapse. To prevent it, add
#container {
display: inline-block;
}
#container {
display: inline-block;
position: relative;
width: 50%;
}
#dummy {
margin-top: 75%; /* 4:3 aspect ratio */
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver;
}
<div id="container">
<div id="dummy"></div>
<div id="element">
some text
</div>
</div>
Using ::before pseudo element, there's no need to use a dummy element:
#container:before {
padding-top: 75%; /* 4:3 aspect ratio */
content: ''; /* Enable the pseudo-element */
display: block;
}
#container {
position: relative;
width: 50%;
}
#container:before {
padding-top: 75%; /* 4:3 aspect ratio */
content: ''; /* Enable the pseudo-element */
display: block;
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver;
}
<div id="container">
<div id="element">
some text
</div>
</div>
You could take advantage of the fact that replaces elements may have an intrinsic aspect ratio.
According to the spec,
Otherwise, if 'height' has a computed value of 'auto', and the element
has an intrinsic ratio then the used value of 'height' is:
(used width) / (intrinsic ratio)
Therefore, you could
Create a replaced element with the desired intrinsic ratio, and then set width:100% to it.
Use absolutely positioning to remove all contents from the normal flow of the element, in order to prevent them from increasing the height. Then, make it grow to fill the container.
Then, the container container will have the aspect ratio that you want.
The replaced element could be an image. You could create images of the desired aspect ratio in PHP, or using a third party web service like http://placehold.it/
In the following snippet, I use a 2px width and 1px height image ():
.container {
border: 3px solid blue;
position: relative;
}
.container > img {
width: 100%;
display: block;
visibility: hidden;
}
.container > .content {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
}
<div class="container">
<img src="http://i.stack.imgur.com/Lfmr6.png" />
<div class="content">
<p>01</p><p>02</p><p>03</p><p>04</p><p>05</p>
<p>06</p><p>07</p><p>08</p><p>09</p><p>10</p>
<p>11</p><p>12</p><p>13</p><p>14</p><p>15</p>
<p>16</p><p>17</p><p>18</p><p>19</p><p>20</p>
</div>
</div>
You can also use a <canvas> element instead of an image. This way you don't need to create images, but it doesn't work on old browsers (like IE 8 and earlier):
<div class="container">
<canvas height="1" width="2"></canvas>
<div class="content">...</div>
</div>
.container {
border: 3px solid blue;
position: relative;
}
.container > canvas {
width: 100%;
display: block;
visibility: hidden;
}
.container > .content {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
}
<div class="container">
<canvas height="1" width="2"></canvas>
<div class="content">
<p>01</p><p>02</p><p>03</p><p>04</p><p>05</p>
<p>06</p><p>07</p><p>08</p><p>09</p><p>10</p>
<p>11</p><p>12</p><p>13</p><p>14</p><p>15</p>
<p>16</p><p>17</p><p>18</p><p>19</p><p>20</p>
</div>
</div>

How do you center an image in a specified area, without resizing the image?

I want to center an image in an area, without resizing... I am using HTML.
Example:
I have an image <img src='img1.png' width='64' height='64'> - the image is actually 64x64. It displays perfectly.
Now, I have another image <img src='img2.png' width='64' height='64'> however, the image is not as big as it should be, its 32x32 - what happens here is it resizes the image to 64x64 and makes it look like $%^&.
How do I make images smaller then the desired width and height centered in the 'img' area without any resizing what so ever?
What you will need is something like this:
<div class="box">
<img src="whatever size image you'd like" />
</div>
And for the styling (in an external stylesheet, natch) you'd apply:
/* Image centering */
div.box {
border: 1px black solid;
height: 64px;
width: 64px;
background: #444;
display: table-cell;
vertical-align: middle;
}
.box img {
display:block;
margin: 0px auto;
}
This works for images with dimensions <= 64x64px, and is easily modifiable to work with larger pics. The key elements here are
set dimensions on the div
display as a table-cell (allows vertical align)
vertical align (aligns on the Y-axis w/out weird hacks)
display:block on the img element
margin: auto centers the image laterally
Solution without IE-unfriendly display:table-cell:
<!DOCTYPE html>
<style>
div {
line-height:64px; /* that's the secret sauce */
text-align:center;
width:64px; height:64px;
}
img {vertical-align:middle}
</style>
<div><img …></div>
You could try putting the image inside a DIV that is 64x64 and not specifying the image dimensions. Then you could style the div so its contents are centered and any overflow is hidden.
You can dynamically get an image size using the getimagesize() php function:
<?php
$size = getimagesize('imgX.png');
$height = $size[1];
$width = $size[0];
?>
<div style="text-align: center">
<img src="imgX.png" width="<?php print($width) ?>" height="<?php print($height) ?>" />
</div>
I've had to do something similar with 36x36 images. Users were able to upload any size but the thumbnails were only to show the center 36 square pixels.
Markup:
<li><div><span></span>
<img src="_media/objects/jessica-bowman.png" alt="Jessica Bowman" /></div>
<p>Jessica Bowman</p>
</li>
The span was just there to get rounded corners on the image, it's not necessarily needed.
CSS:
ul.recent-list li div {
position: relative;
float: left;
width: 36px;
height: 36px;
overflow: hidden;
}
ul.recent-list li div span {
position: relative;
z-index: 100;
display: block;
width: 36px;
height: 36px;
background: url("../_media/icons/icon-overlay.png") top left no-repeat;
}
ul.recent-list li div img {
position: relative;
top: -36px;
z-index: 0;
float: left;
}
JavaScript:
$(window).load(function() {
$("ul.recent-list div img").each(function() {
var moveX = ($(this).width() / 2 * -1) + 18;
var moveY = ($(this).height() / 2) * -1 - 18; // 18 is 1/2 the default offset of 36px defined in CSS
$(this).css({'top' : moveY, 'left' : moveX});
});
});
The solution is a simple bit of CSS + HMTL
<img src="transparentpixel.gif"
width="64"
height="64"
style="
background-image:url('path/to/image.jpg');
background-repeat:no-repeat;
background-position:center center;
" />
the transparentpixel.gif is a simple 1x1px transparent gif image
An img tag with width and height attributes is saying "stretch or shrink the image to this size regardless of its actual size". use something like:
<div style="text-align:center;">
<img src="x.jpg">
</div>
and no i don't know why text-align would work, but it appears to in my experience.
Use CSS to render the image using background:
<div style="background: url(img1.png) no-repeat center center; height: 64px; width: 64px;"></div>
This will show the image in the center, without scaling it.

Categories