I am currently using WKHTMLTOPDF to generate PDFs through my Laravel application. The PDF template uses Bootstrap 3.3.6.
What I'm currently seeing is that the text, font, layout renders perfectly, but text is cut off from the left-margin.
If I remove the call for the Bootstrap CSS, it doesn't cut off the text, but the tables etc.. aren't aligned/laid out correctly. It must be something in Bootstrap that's causing this issue.
Top of template
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'>
<link href="https://fonts.googleapis.com/css?family=Lato:100,300,400,700" rel='stylesheet' type='text/css'>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
width: auto !important; min-width: 100% !important;
font-family: 'Lato';
}
.page-break {
page-break-after: always;
}
</style>
The line width: auto !important; min-width: 100% !important; makes more of the text visible, but it's still not perfect (see screenshot below on the second page):
Any text wrapped in<p> </p> fits on the PDF correctly, but the headers and tables etc.. are cut off on the left hand side.
Controller code:
$pdf = PDF::loadView('reports.view-full-audit-report', $data)
->setPaper('a4')
->setOrientation('portrait')
->setOption('encoding', 'utf-8');
return $pdf->download('auditReport.pdf');
Has anyone experienced this before? If so, how did you resolve it? If you require further code samples, please let me know. Many thanks.
I have experienced this before, on Frappé Framweork and ERPNext. The HTML rendering for a DocType (Sales Invoice) will do this for mysterious reasons. So far I have found two workarounds:
1. Set the viewport size in the HTML code as per your final document size. For example, an 8.5 x 11 Letter sized page would be:
<style>
#media screen {
.print-format {
width: 21.59cm;
min-height: 27.94cm;
padding: 0.0cm;
}
}
</style>
I think you can use inches or other accepted measurements as well. You must declare an adequate viewport size on the HTML or Jinja template by doing the above solution
If all else fails, I solved my problem alternatively with the following styles and HTML:
<style>
div.general{
position: relative;
top: 0.0cm;
/*left: 0.0cm; */
}
div.document_size{
position: absolute;
width: 21.59cm;
height: 27.94cm;
}
</style>
<div class="general">
<div class="document_size">
<!-- YOUR HTML GOES HERE -->
</div>
</div>
Finally, to carefully position your elements on the page, use the span tag, with a declared class style, so you can place it in absolute terms within the divs created above. Distances are measured from the top left (origin) of the document:
span.item1{
position: absolute;
top: 1cm;
left: 1cm;
}
Once you have placed the span class= "item1" within the div tags as above, you can place anything you want within them. I consider these span tags as a sort of coordinate system marker, that ensures consistent output on every generation of wkhtmltopdf.
Related
I'm looking into building an editor with Slate or ProseMirror and seeing some strange behavior with Chrome around the caret position and selection area when using an inline element. Issue 1 is shown in the first picture below. When the text cursor position is behind the "f", the caret is shown at the top of the image. Issue 2 is in the second image - selecting the text shows a highlighted area that's as tall as in the inlined element. Is there any way to control this behavior and instead have the caret show at the position of the text and only highlight the space around the text (even if the inline image is making the line height larger)
I'd like to mimic the behavior here, from firefox:
Example images were produced using the ProseMirror demo here: https://prosemirror.net/examples/basic/
A minimum example (thanks #Kaiido) with JSBin:
<div contenteditable>Test text<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png">Testing</div>
Not sure how this behaves on other operating systems, but I'm using macOS Catalina.
You can fix the selection problem by using flexbox. I originally tried using align-items: flex-end but I was getting some weird arrow key behavior. align-items: baseline seems to work as of now.
The image problem is very strange. I noticed that Chrome steps over SVG elements differently than IMG elements. As of now, the latest version of Chrome "waits" before skipping over IMG, but allows the user to skip over an SVG like any other character (left arrow skips character closest to svg). This may be caused by underlying default styles, but I do not know.
I was about to post my findings, but I realized that Firefox did not work the same. Firefox has some really weird arrow key behavior when using SVG and/or Flexbox. The cursor goes above the image, but only when pressing the right arrow key.
However, Firefox works just fine with a normal IMG element.
Long story short, you will have to render different image elements based on the browser.
// chrome contenteditable ads spaces between spans.
// firefox does not, so you have to add them manually.
if (navigator.userAgent.indexOf("Firefox") > 0) {
Array.from(document.querySelectorAll('#editable span')).forEach(el => {
el.innerHTML += " "
})
}
.flexit {
display: flex;
align-items: baseline;
flex-wrap: wrap;
}
span {
display: inline-block;
white-space: pre;
}
.img-wrapper, .img-wrapper + span {
display: inline;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<h1>chrome</h1>
<div contenteditable="true" class="flexit">
<span>test</span><svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/>
</svg><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>
</div>
<h1>firefox</h1>
<div contenteditable="true" id="editable">
<span>test</span><span class="img-wrapper"><img src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200" /></span><span>test</span><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>
</div>
</body>
</html>
P.S. A lot of editors I have used default to full-width images.
Edit: I just realized that it appears my Firefox solution also works in the latest Chrome. I think this works because I wrapped the text nodes in SPAN elements. The SVG element still works differently in Chrome, but wrapping text in SPAN seems to solve most of the problems.
First, don't manipulate the ProseMirror DOM as shown in the JQuery example. In fact you most likely will run into DOM or content issues. ProseMirror uses its own DOM node and markup schema. If you want to manipulate the ProseMirror DOM or add plugin then take a look at the Markup, Plugin & Node Apis. Ive attached a simple example of text align Markup code. Side note, the reason Grammarly and others don't have ProseMirror plugins is because of the DOM approach / models. I should add the ProseMirror is very good, but to be honest it is more of an advanced developer solution.
That aside, the good news the problems you have a purely CSS. ProseMirror strips out all classes and resets the DOM / CSS so if you import a document or cut and paste all / most your classes will be gone.
Simplest approach to solve that is to wrap the editor in a div and assign a class to the div then add styles and child styles to that class. The reason to wrap it is that the css selectors such as img, p, h, etc will only apply to the tags inside of the editor class. Without that you end up with obvious CSS clashes.
CSS
Don't use flexbox for inline images as flexbox is not a grid system. In fact, if I recall you cannot inline direct children of the flex container.
inline on p tags and img will not wrap text and you will end up with the problems listed above.
if you want to truly wrap and remove the cursor issue your have then you need to use floats e.g. float: left; (recommended approach)
add small or large padding and border boxing to help with collapsing edges and also helps with separation of image and text
the cursor problem you are experiencing is because when you inside the image block it vertically aligned to top, which you can fix with vertical-align: baseline; but without floats you will still have a cursor that matches the height of the image and not the text. Also, if you don't use floats the cursor will be elongated as the line height is effectively the same height as the image. The blue color is just selector, which you change using CSS as well.
<html>
<div class="editor">
<!-- <editor></editor>-->
</div>
</html>
<style>
.editor {
position: relative;
display: block;
padding: 10px;
}
.editor p {
font-weight: 400;
font-size: 1rem;
font-family: Roboto, Arial, serif;
color: #777777;
display: inline;
vertical-align: baseline;
}
.editor img {
width: 50px;
float: left;
padding: 20px;
}
</style>
Node extension example
Example of Node extension for text align that can be added as a toolbar. Much longer post, but even if you did create a Node / plugin for images you have to deal with the manner in which it render i.e. base64 versus url, etc. which btw, makes perfect sense as to why they did that, but just add complexity to developers looking for SEO, etc.
export default class Paragraph extends Node {
get name() {
return 'paragraph';
}
get defaultOptions() {
return {
textAlign: ['left', 'center', 'right'],
}
}
inputRules({ type }) {
return [
markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
]
}
get schema() {
return {
attrs: {
textAlign: {
default: 'left'
}
},
content: 'inline*',
group: 'block',
draggable: false,
inclusive: false,
defining : true,
parseDOM: [
{
tag: 'p',
style: 'text-align',
getAttrs: value => value
}
],
toDOM: (node) => [ 'p', {
style: 'text-align:' + node.attrs.textAlign,
class: `type--base type--std text-` + node.attrs.textAlign
}, 0 ]
};
}
commands ({ type }) {
return (attrs) => updateMark(type, attrs)
}
}
I tried to do a little hack with HTML and css.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div contenteditable><p class="new1" contenteditable>Hello</p><div contenteditable>
<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png"></div>
<p class="new2">Testing</p>
</div>
</body>
</html>
//css
.new2{
font-size:30px;
margin-top:-35px;
margin-left:252px;
padding-left:79px;
}
img{
margin-left:75px;
padding-left:5px;
padding-right:5px;
margin-top:-300px;
}
.new1{
text-overflow:hidden;
padding-top:260px;
margin-bottom:-20px;
font-size:30px;
padding-right:10px;
}
Here is jsfiddle https://jsfiddle.net/wtekxavm/1/
I would like to know if there is a way to use a particular css page as styling for a tag.
For example, instead of
<div class="header" style="position: absolute; text-align:left; right: auto; margin: 0 auto 20px; z-index: 1; width: 60%; height: auto; left:9%">
Is there a way to specify style.css for the div tag?
For example,
This style.css must ONLY apply to the div tag above.
Also, is it possible for all tags contained within that div tag to follow the same specified css page?
Put this in the header of your page
<head>
<link rel="stylesheet" href="/styles.css" type="text/css">
</head>
If you want to specify style for a page, include that CSS when you render the page.
If you want to have multiple ways of rendering a particular tag, differentiate the tags.
I'm not aware of conditional logic you can apply to the CSS directly.
HTML:
(include this in the head)
<link href='style.css' rel='stylesheet' type='text/css'/>
CSS: (in the style.css file)
div.header{
//your style here
}
or without the class:
div{
//your style here
}
but without the class it will get all div tags so I recommend the first code
You can create the CSS page you want and then create the styling you want inside
something like this
div > table {
padding: 5px;
}
That would make the div have a padding of five as well as it's child the table a padding of 5
I'm new to HTML and CSS in general. Please help me with the code. I cannot get the background-image to appear in my browser although i typed the syntax correctly. All i get is an orange box, with no alert.png image. I'm following an online tutorial btw: http://dev.opera.com/articles/view/31-css-background-images/#thecode
Edit 1: The image, html file and css file are all inside the same folder. Yet no success.
Edit 2: I used an unique css file name instead of a generic "style.css" (which i have several of them in my system) and it worked! Make sure there's no space between url and the parenthesis.
HTMl code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>alert message</title>
</head>
<body>
<p class="alert">
<strong>Alert!</strong>
This is an alert message.
</p>
</body>
</html>
CSS code:
.alert {
width: 20em;
background-image: url(C:\Documents and Settings\USER\My Documents\alert.png);
background-color:orange;
margin: auto;
padding: 2em;
}
The url must be a string:
url("C:\Documents and Settings\USER\My Documents\alert.png");
I would guess it's a permissions issue, regardless you will most likely have problems with the URL being a file reference when you move this to a server, I would recommend moving your image into the same location (or better yet an image folder in the root of your site) as your html file and then modify your css to be this
.alert {
width: 20em;
background-image: url('/alert.png'); /* '/images/alert.png' */
background-color:orange;
margin: auto;
padding: 2em;
}
Another way of doing things is to put your text into a div, and set the image as the div's background image using css, like so:
<div class="alert">
<p>
<strong>Alert!</strong>
This is an alert message.
</p>
</div>
And, for the CSS:
.alert {
width: 20em; (Width of entire div, which includes text and bg image)
background-image: url('../alert.png');
background-color: orange;
margin: auto;
padding: 2em;
}
You can see the live JSFiddle example here: http://jsfiddle.net/Cwca22/TdDJY/
Also, in the code above, the background image will tile (repeat) both horizontally and vertically to fill the space of the div. In order to prevent this, you could make the div the same height and width as your background image, or put background-repeat: no-repeat in your css under the .alert class.
Hope this helps and good luck!
Please check your URL, if possible you can use firebug which is addon of firefox, which will definitely help you, by indicating if image has been loaded or not.
Else another solution would be give height to your alert class as follows
.alert {
width: 20em;
background-image: url('/alert.png'); /* '/images/alert.png' */
background-color:orange;
margin: auto;
padding: 2em;
height: /* height of image*/
}
First put your alert.png picture in the same folder as your html file.
Then try this in your CSS file:
body {
background: orange url("alert.png") no-repeat;
}
I think the problem was the "\" in \alert.png
Good luck!
In the original question he had in his css
background-image: url(C:\Documents and Settings\USER\My Documents\alert.png);
I ran into problems with a gallery page that had images as background thumbnails. Any image filename that had spaces would not appear. It was only the fact that one image happened to have underscores in place of spaces and that did appear that I was able to track it down. As there are spaces in his url, this could be the problem. I fixed my problem by using \ to escape any characters like spaces causing the problem. i.e.
A\ space\ in\ the\ filename.jpg
though this might not work in a Windows pathname!
If the image is in the same directory as the script he shouldn't need the full url anyway.
What I need is for the footer to print at the bottom of each page (when it is printed on paper, not printed on screen, that's easy)...
I am using tables, I know tables are bad, I typically do not use them, but this is a special case: (I am using a C# webBrowser control, and just using HTML to format a document to print).
It works fine, except for the footer on the LAST page printed...the first pages it is sitting at the bottom, because the page content pushes it to the bottom, but on the last page, it is just at the bottom of the content still (and the content does not go to the bottom of the page)
Here is an image to show (this is when I go print preview of my webBrowser). dont mind the green text, just there for testing.
good and bad footer http://pdem.info/badfooter.png
As you can see, on the left, the footer is forced at the bottom by content, and on the right side, the footer is in the same position relative to content, but I want it at the bottom!
The snippet for my footer is just:
<tfoot id='footer'><tr><td>Your footer goes here</td></tr></tfoot>
Any ideas how to force the footer to be at the bottom? I have no objection to using div's if there is a way to make it work like that!
=========EDIT=========
Here is some of the code:
The css:
#media print {
thead { display: table-header-group; }
tfoot { display: table-footer-group; }
//I have tried doing position:absolute/fixed with values in pixes and percents
}
#media screen {
thead { display: none; }
tfoot { display: none; }
}
Code that populates the webBrowser Control:
web_display.DocumentText = "";
web_display.Document.Write("<body><table id='tblCont'><thead><tr><td>Your header goes here</td></tr></thead>" +
"<tbody><tr><td>");
web_display.Document.Write("<body><basefont size='2' face='verdana'>");
web_display.Document.Write("<ul " +
"style='list-style:none;"+
"padding-left:0px;"+
"margin-left:0px;"+
"'>");
foreach (TNode part in tn.Nodes) {
web_display.Document.Write("<li><strong>" + part.Text + "</strong>");
web_display.Document.Write("<ul style='list-style:none;'>");
foreach (TNode node in part.Nodes) {
web_display.Document.Write("<li><strong>" + node.Text + "</strong></li>");
web_display.Document.Write("<ol>");//this list will hold the textblock text
addTextBlk(web_display, node);
web_display.Document.Write("</ol>");//end textblock list
web_display.Document.Write("<br style='line-height:6px;'/>");
}
web_display.Document.Write("</ul>");//end lvl2 list
web_display.Document.Write("</li>");//end part item
}
web_display.Document.Write("</ul>");//end part list
//web_display.Document.Write("</li>");//end section item
web_display.Document.Write("<br />");
//web_display.Document.Write("</ul>");//end section list
web_display.Document.Write("</td></tr></tbody><tfoot id='footer'><tr><td>Your footer goes here</td></tr></tfoot>" +
"</table><div id='newFooter'>This is footer text</div></body>");
<style type="text/css">
#footer
{
position:absolute;
left:200px;
top:750px;
}
</style>
Change the left: and top: to suit your page.
that will position it absolutely in the exact place you want.
EDIT - Note: My solution was posted prior to what looks like it may have been an edit (no picture was displayed when I first read the question and less information) on the question that changed it, the answer is now irrelevant sorry. This may be able to help you anyway with something else.
For consistency through multiple pages I would personally use a div.
Next option, CSS like (off the top of my head I don't know if this will work)
#footer {
height:100%;
vertical-align:bottom;
}
EDIT ENDS HERE
I use the print and screen media types for this, in the of your page include a stylesheet like this:
<link rel="stylesheet" href="style.css" type="text/css" media="print" />
Make sure your other 'screen' stylesheet is tagged with media="screen"
Now in your stylesheet put in the code for your footer as you would like to see it printed, in this example I'm using a div tag:
#print_footer { border:0 solid #333; font-family:arial; font-size:8px; color:#000; margin-bottom:0; }
Open your normal 'screen' stylesheet add the following class
.no_screen { display:none; }
This will stop the element from displaying on the screen.
In your page create your DIV
<div id="print_footer" class="no_screen">Copyright © 2011 Ryan. All rights reserved.</div>
I hope this helps.
I am using CSS Sprite Generator to create sprites for a web page I am working on, but it doesn't seem to work, and I don't know why...I guess it's something obvious but..!
So, I picked up 3 images, zipped, generated the PNG file (I checked out the result it is seems fine) and I got the following css classes back:
.sprite-welcom1 { background-position: 0 -30px; }
.sprite-welcom3 { background-position: 0 -109px; }
.sprite-3 { background-position: 0 -188px; }
So here is the HTML I am testing on, and for some reason all I get is a nice blank page:
<html>
<head>
<style>
.sprite-welcom1 { background-position: 0 -30px; }
.sprite-welcom3 { background-position: 0 -109px; }
.sprite-3 { background-position: 0 -188px; }
.sprite-bg {
background: url(csg-495a902b04181.png) no-repeat top left;
}
</style>
</head>
<body>
<div class="sprite-bg sprite-3"></div>
</body>
</html>
Any tips?
Don't use a generator. Take the time to do it yourself from scratch. Then next time you use this method, you'll know what to look for when something has gone wrong and you'll answer your own question, and heck, maybe someone else's on Stack Overflow.
This generator isn't producing any meaningful class names for your styles, which means if you go to edit them later you're not going to know two classes from Tuesday what's going on unless you've memorized the numbers. Meaningful names will save you headaches when you return to your stylesheet later on.
Open up Photoshop, GIMP, or almost any modern image editing software. Make sure your program has the rulers option switched on, and measure your element's background image coordinates this way. In the absence of rulers - which is probably a rarity, you could always fudge around with the MeasureIt Firefox extension and the .png opened in a tab.
Define a width and height for <div class="sprite-bg sprite-3">.
Your .sprite-bg rule for background-position, set as part of the composite rule for background (the top left part), has higher precedence than the stand-alone background-position setting for .sprite-3 because it appears later in the stylesheet.
Place the rule for .sprite-bg first.
the div is empty. put something inside. like space ( ).
You have to declare a height and width for the div element. That's it.
Hrm, not quite sure what you're trying to achieve here. The multiclassing seems a bit messy. I've posted my method of spritemaps below, see if this does what you need. Usually this involves a combination of elements, the most common being an unordered list with links for navigation, but for this purpose it's just divs.
Also don't forget the order of background-position.
background-position: |top| |left|;
That's screwed me up a couple of times. Finally, A List Apart has a great article on Sprite Maps (http://www.alistapart.com/articles/sprites/)
<html>
<head>
<style>
.sprite-container div {
background: url(csg-495a902b04181.png) top left no-repeat;
width: 20px; //width is neccessary
height: 20px; //height is neccessary
}
.sprite-3 { background-position: 0 -188px; }
.sprite-4 { background-position: -20px -188px; }
</style>
</head>
<body>
<div class="sprite-container">
<div class="sprite-3"></div>
<div class="sprite-4"></div>
</div>
</body>
</html>
As others have mentioned, your sprite-bg element needs to have either some content to give it a height / width, or have those properties specified in the css, thusly:
.sprite-bg {
background: url(csg-495a902b04181.png) no-repeat top left;
width: 100px; /* (or whatever the width should be) */
height: 100px; /* (or whatever the height should be) */
}
As someone else mentioned, I'd move the rules for the .sprite-welcom1, .sprite-welcom3 and
.sprite-3 to beneath the main .sprite-bg in the stylesheet.
For some reason, Firefox 3 sometimes wants 2 classes in the CSS Selector to make the sprite map work. My hunch is that the rules of specificity are causing problems while the sprite map loads. By adding the additional class, it works correctly.
/* Bad */ .childClass2 { background-position: -10px -20px; }
/* Good */ .parentClass1 .childClass2 { background-position: -10px -20px; }
It's always good to “namespace” your CSS with a parentClass, to avoid unexpectedly styling a DOM tag someplace else. Here are some additional enhancements to everyones ideas from above.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
.sprite-container div {
background: transparent url(//www.yourDomain.com/csg-495a902b04181.png) no-repeat scroll 0 0;
width: 200px; /* width is necessary */
height: 20px; /* height is necessary */
}
.sprite-container .sprite-3 { background-position: 0 -188px; }
.sprite-container .sprite-4 { background-position: -20px -188px; }
</style>
</head>
<body>
<div class="sprite-container">
<div class="sprite-3"></div>
<div class="sprite-4"></div>
<!-- Empty divs are fine! Unless you *really* want text on top of
your sprite map. :o) Btw: is invisible when a hyperlink
is wrapped around it.   is not... it creates an
underscored hyperlink. Use which is a soft-hyphen.
-->
</div>
</body>
</html>
This code works in: IE 7, Firefox 3, Google Chrome 1, Opera 9 & Safari 3.
Tip: Avoiding http:// in the URL will allow the sprite map to be served up from both http:// and https:// connections.
(Scroll to the right to see the “no-repeat scroll 0 0;” )