Print when textarea has overflow
Asked Answered
E

12

45

I have a form with some text areas that allow a scroll bar when the text exceeds the text box. The user would like to be able to print the screen, and this text is not visible. How do I make all of the text visible for just printing? Am I better of making a print to pdf link or something?

Expectorate answered 14/12, 2010 at 4:34 Comment(4)
Notice: The accepted answer was not researched or tested and is factually incorrect. There is unfortunately no CSS-only, cross-browser solution, but several JavaScript-based workarounds are possible (my answer suggests two, both of which I have done in practice).Jecon
Alan H, I accepted the answer because it worked for me and my environment. I don't need cross-browser solutions and all that stuff. You still haven't given me an example. If you are trying to get a tick from me then you will have to show me your solution in practice.Expectorate
Timothy, that’s all well and fine. However, this page is not just for your own benefit, but also potentially hundreds or thousands of other developers. I’m guessing most of them do prefer cross-browser solutions, and only mean to do them a favor by pointing out the above (not to criticize you).Jecon
I have updated my answer to include a working JavaScript solution.Jecon
J
74

You cannot solve this problem with CSS alone.

Why Pure-CSS Solutions are Insufficient (with demo)

Let me convince you the answers involving print stylesheets and overflow: visible are insufficient. Open this page and look at the source. Just what they suggested, right? Now print preview it (in, say, Chrome 13 on OS X, like me). Note that you can only see a line or two of the note when you attempt to print!

Here’s the URL for my test case again: https://alanhogan.github.io/web-experiments/print_textarea.html

Solutions:

  1. A JavaScript link that opens a new window and writes the contents of the textarea to it for printing. Or:

  2. When the textarea is updated, copy its contents to another element that that his hidden for screen but displayed when printed.

  3. (If your textarea is read-only, then a server-side solution is also workable.)

Note that textareas treat whitespace differently than HTML does by default, so you should consider applying the CSS white-space: pre-wrap; in the new window you open or to your helper div, respectively. IE7 and older do not understand pre-wrap however, so if that is an issue, either accept it or use a workaround for them. or make the popup window actually plain text, literally served with a media type text/plain (which probably requires a server-side component).

The “Print Helper” Solution (with code + demo)

I have created a demo of one JavaScript technique.

The core concept is copying the textarea contents to another print helper. Code follows.

HTML:

<textarea name="textarea" wrap="wrap" id="the_textarea">
</textarea>
<div id="print_helper"></div>

CSS (all / non-print):

/* Styles for all media */
#print_helper {
  display: none;
}

CSS (print):

/* Styles for print (include this after the above) */
#print_helper { 
    display: block;
    overflow: visible;
    font-family: Menlo, "Deja Vu Sans Mono", "Bitstream Vera Sans Mono", Monaco, monospace;
    white-space: pre;
    white-space: pre-wrap;
}
#the_textarea {
  display: none;
}

Javascript (with jQuery):

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($){
  function copy_to_print_helper(){
    $('#print_helper').text($('#the_textarea').val());
  }
  $('#the_textarea').bind('keydown keyup keypress cut copy past blur change', function(){
    copy_to_print_helper(); // consider debouncing this to avoid slowdowns!
  });
  copy_to_print_helper(); // on initial page load
});
</script>

Again, the successful JavaScript-based demo is at https://alanhogan.github.io/web-experiments/print_textarea_js.html.

Jecon answered 6/1, 2011 at 2:31 Comment(13)
Could you give me an example of how to use it in javascript? That would help me a lot more.Expectorate
Javascript is not necessary. It can be done with pure CSS. It's rather a pain in the neck though. See my answer.Yah
@Timothy-Ruhle Updated with a demo!Jecon
@Yah Your “pure CSS” answer requires PHP and and does not allow for the case where the user edits the textarea before printing.Jecon
btw - i have enhanced your answer and created a "plugin" (only can be used when doing window.print() :) @ stackoverflow.com/a/10600643/57508Tubulure
Great answer, and even more importantly, works really well with javascript data binding frameworks, like angular and ember.Oatis
Alan: Your demo no longer works because Dropbox is now forcing https and you are loading jquery via http. See error console in Chrome for details.Literalminded
@AllInOne: Thank you for the report! I have switched my page to load the script with HTTPS. Let me know if it works for you now.Jecon
Note: you may need to make sure all the parents of the print helper are height: autoWildee
All the samples gives 404s. Maybe it's safer to move to a gist or JsFiddlePhilips
@EduardoMolteni Thank you very much for letting me know. Dropbox stopped allowing web pages to be served from their service; I have updated the URLs above to point to the GitHub Pages site I previously set up as an alternative. (They should work now!)Jecon
@AlanH. thanks for the solution. How can I achieve the same for multiple text areas on the same page?Dermoid
@AlanH. I'm several years late to this. Your solution works great - like Bogdan, I also need to figure out how to loop through several textarea/"print helper" divs to make this happen. I actually need to do it 21 times on a page.Purgatory
R
10

Loop through each of your text areas and move the content to a holder

    window.onbeforeprint = function () {
        $('.print-content').remove();
        $('textarea').each(function () {
            var text = $(this).val();
            $(this).after('<p class="well print-content">' + text + '</p>');
        });
    }

And use the following CSS

.print-content {
  display: none !important;
}

@media print {
  .print-content {
    display: block !important;
  }
  textarea {display: none !important;}
}
Rawdon answered 14/4, 2015 at 15:41 Comment(0)
Y
3

I recently ran into the same issue. My solution was to duplicate the content into form controls for editing and into divs for printing.

In my Head I put a print stylesheet.

<link rel="stylesheet" href="printform.css" type="text/css" media="print" />

In printform.css I put the following

.screenOnly { display: none; }
.printOnly { display: inline-block; }

For textareas (and other field types that were causing problems) I used the following code

<textarea class="screenOnly" name="myTextArea"><?php echo (htmlspecialchars ($_POST ['myTextArea'])); ?></textarea>
<div class="printOnly"><?php echo (htmlspecialchars ($_POST ['myTextArea'])); ?></div>

When displayed on screen the textareas are shown and the divs duplicating their content are hidden. When printing the opposite applies.

I know you already picked an answer to this question but while using the print stylesheet is a good idea it didn't describe a specific solution. Setting overflow:visible on the textarea (my first idea) didn't work so I ended up going with the solution above. If you're still having difficulties I hope this helps you out

Yah answered 31/1, 2011 at 12:59 Comment(2)
What is the point of using a textarea if you’re going to echo its contents again with PHP and then assume the user will not edit it before printing? While this technique could be useful, I don’t think you should be selling your solution as "CSS-only" as it assumes PHP and a narrow, unlikely use-case.Jecon
The example code is in PHP because it had to be in something. It should be possible to do something similar in most languages used for web scripting. And yes, this technique does have limitations, but as you can't overflow:visible a textarea there's always going to have to be some compromise made. I suppose if you need to print out a form before its committed to the server you could also add some javascript to synchronise the textareas with their respective divs. This, however, adds a javascript dependency so it won't work if js is off.Yah
O
1

Just encourter the problem recently too. Thanks for Alan H's posts. It works perfect with Chrome and Safari. However, with IE and Firefox, the issue is that the last several pages(page elements after textarea) will be missing from printing(FF), missing pages and overlapped layout(IE9).

Another finding that will be helpful to solve the issue is, you can set textarea's rows properties correctly as the control's height says to make it work with CSS overflow:visable stuff. All browsers seems to respect the rows property while printing.

Ochrea answered 28/2, 2012 at 2:20 Comment(0)
N
1

This seems to work for applying to all elements that have overflowing content:

$("textarea").each(function () {
    var Contents = $(this).val();
    if ($(this)[0].scrollHeight > $(this).height()) {
        $(this).after("<div class='print-helper'>" + Contents + "</div>");
        $(this).addClass("no-print");
    }
});
Neocolonialism answered 9/4, 2014 at 18:40 Comment(0)
G
0

This is an easy fix with CSS, given that most users aren't really bothered about printing a bit of extra blank space. Just target a minimum height for textareas when printing:

@media print { 
textarea {
min-height: 500px;  
}
}

Tag that onto the end of your CSS with a min-height that is comfortably enough when you look at it in Print Preview.

Gader answered 12/8, 2016 at 12:15 Comment(0)
J
0

With the usage of pure CSS it is not possible to prepare the textarea for printing.

It is necessary to add some javacript magic to the text area or add a hidden field.

There are a couple of solutions, that have been mentioned here:

  1. Hidden paragraph or div
  2. Using Javascript to extent the size of the textarea

1. Hidden paragraph or div

HTML & CSS:

<textarea>Sample Text</textarea>
<div class="hidden-div">Sample Text</div>

<style>
  .hidden-div{display: none;}
  @media print{
    .hidden-div{display:block;}
  }
</style>

2. Javascript

You could use a js library e.g https://github.com/thomasjo/jquery-autoresize

$(function() {
    $("textarea").autoResize()
})
Joanjoana answered 26/9, 2017 at 14:39 Comment(0)
S
0

Adding onto Alan's answer above, if you have multiple instances of this problem on the same page, then you can use data-* attributes to handle all at once. Sample:

var $printOnlyArr = $('.print-only');
for (var i = 0; i < $printOnlyArr.length; i++) {
  var $printOnly = $($printOnlyArr[i]);
	var textSource = $printOnly.data('textsource');
	if (textSource) {
	  $printOnly.text($("#" + textSource).val());
	}
}
.print-only {
	display: none;
}

@media print {
	.print-only {
		display: block;
	}
	.no-print {
		display: none;
	}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea class="form-control no-print" maxlength="2000" id="txtAdditionalComments"></textarea>
<div class="print-only" data-textsource="txtAdditionalComments"></div>
Safeconduct answered 15/4, 2019 at 17:12 Comment(0)
E
0

I had this same problem. My project is React, I was a semnaticUi TextArea component. The Text that could only be seen by scrolling down in the Textarea aka the "overflow" could not be seen in the print view when I press the print screen button.

Solution :)

I just used a normal paragraph tag instead and set css white-space: pre-wrap on a div that enclosed the p tag.

Worked for me!

Episcopacy answered 21/1, 2020 at 19:38 Comment(0)
D
0

try this using jQuery. Redefine height of all textareas based on quantity of lines.

Attention: this code change the textarea on screen too

window.onbeforeprint = function () {
    $('textarea').each(function () {
        var lines = Math.round($(this).val().split('\n').length * 1.6) ; //multiply to 1.6 to consider spacing between lines
        $(this).height(lines+'em');
    });
}
Diastyle answered 10/7, 2021 at 10:25 Comment(0)
B
-1

Define a separate CSS for print media like this <link rel="stylesheet" href="print.css" type="text/css" media="print" /> and for the text area, define the overflow attribute as

overflow: visible;
Barby answered 14/12, 2010 at 4:48 Comment(1)
It seems, this answer and the answer accepted as solution are same.Barby
H
-2

I use this in my styling:

PRE.print {
display:none;
}

@media print {

  TEXTAREA {
    display:none;
  }

  PRE.print {
    display:block;
    width:90%; /* fixes margin issues in some funky browsers */
    white-space: pre-wrap;       /* css-3 */
    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
    white-space: -pre-wrap;      /* Opera 4-6 */
    white-space: -o-pre-wrap;    /* Opera 7 */
    word-wrap: break-word;       /* Internet Explorer 5.5+ */
    font-family:monospace,sans;
  }

}

Then, after every TEXTAREA, I use a PRE with class "print" like so:

<textarea id="message" name="message" rows="10" cols="80" onblur="updatePrint('#message')"><?= $MESSAGE ?></textarea>
<pre id="message-print" class="print">
<?= $MESSAGE ?>
</pre>

...note the PHP I used -- you can switch with your programming language. And then this code above needs the following function, assuming you have jQuery library loaded:

<script type="text/javascript">

function updatePrint(sID) {
  $(sID + '-print').text($(sID)[0].value);
}

</script>

The way this all works

The way this works is that I'm basically loading content twice into the page, but using the stylesheet to hide content not suitable for the printer like the TEXTAREA.

You can change the PRE styling as you wish. However, I use monospace in case someone was wanting to print HTML code that they typed into the field and wanted it to format nicely.

The onblur event helps capture a need to update the related PRE.

Note you can also do the stylesheet stuff via the media attribute on a link rel in the HEAD section of your HTML, using things like media="all not print" and media="print".

Holdfast answered 9/1, 2012 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.