Quick ref
Parameters, querying and setting
HTML tags, overriding
Headers
Redirecting
URL, getting the script's
HTML document, starting
HTML document, ending
HTML, standard elements
HTML shortcuts, distributive property of
HTML shortcuts, non-standard
HTML characters, autoescaping
Printing args without spaces
Forms, starting and ending
Forms, textfield, creating a
Forms, textarea, creating a
Forms, password field, creating a
Forms, upload field, creating a
Forms, upload field, responding to errors
Forms, popup menu, creating a
Forms, scrolling list, creating a
Forms, checkboxes, related, creating
Forms, checkboxes, standalone, creating
Forms, radiobutton group, creating a
Forms, submit button, creating a
Forms, reset button, creating a
Forms, default button, creating a
Forms, hidden field, creating a
Forms, clickable image button, creating a
Cookie, creating a
Cookie, retrieving a
Style sheets example
Debug, dumping name/value pairs
Environmental variables, fetching
A complete example of a simple form-based script
Javascript, style
Don't import :standard: if using CGI object print $q->header, # content-type $q->start_html('hello world'), # html + body, title $q->h1('hello world'), # h1 $q->end_html; # body + html Routines allowing multiple args: print $q->header(-type=>'image/gif',-expires=>'+3d'); Each argument name is preceded by a dash. Neither case nor order matters in the argument list. Routines allowing one args: print $q->header('text/html'); Provide the single argument without an argument name. HTML tags have both attributes and contents (the part between the opening and closing pairs.) Pass HTML attributes as a hash reference as the first argument, and the contents, if any, as any subsequent arguments. Examples: Code Generated HTML ---- -------------- h1() <H1> # is this correct? missing </H1>? h1('some','contents'); <H1>some contents</H1> h1({-align=>left}); <H1 ALIGN="LEFT"> h1({-align=>left},'contents'); <H1 ALIGN="LEFT">contents</H1>
@keywords = $q->keywords @names = $q->param @values = $q->param('foo'); $value = $q->param('foo'); $q->param('foo', $newValueForFoo); # additional values can be provided (e.g. array elements) $the_string = $q->query_string; URL SAMPLE VALUE OF $the_string c.pl?test keywords=test c.pl?test1&test2 test1=;test2= c.pl?test1=1&test2=2 test1=1;test2=2
There will be some times when you want to produce the start and end tags yourself. In this case, you can use the form start_*tag_name* and end_*tag_name*, as in: print start_h1,'Level 1 Header',end_h1; You can specify the tags you want to generate *start/end* functions for by putting an asterisk in front of their names in the import list. use CGI qw/:standard *table *ul/; In this example, the following functions are generated in addition to the standard ones: 1. start_table() (generates a <TABLE> tag) 2. end_table() (generates a </TABLE> tag) 3. start_ul() (generates a <UL> tag) 4. end_ul() (generates a </UL> tag)
QUICK REF # returns Content-type of text/html $q->header OR $q->header('text/html') # returns Content-type of image/gif with expiration date $q->header(-type=>'image/gif',-expires=>'+3d') # other variations $q->header( -type=>'text/html', -status=>'402 Payment required', -expires=>'+3d', # overrides default of refresh to use same script result for 3d -cookie=>$cookie, # sets cookie -attachment=>'foo.gif', # (might) prompt user to save the named file -charset=>'utf-7' ) The curly braces are required for HTML attributes and optional for other routines. For example: print $q->header( {-type=>'image/gif',-expires=>'+3d'} ); Many routines will do something useful with a named argument that it doesn't recognize. For example, some non-standard HTTP headers fields: print $q->header( -type => 'text/html', -cost => 'Three smackers', -annoyance_level => 'high', -complaints_to => 'bit bucket' ); Resulting non-standard HTTP header: HTTP/1.0 200 OK Cost: Three smackers Annoyance-level: high Complaints-to: bit bucket Content-type: text/html print $q->header( -type=>'text/html', -status=>'402 Payment required', -expires=>'+3d', -cookie=>$cookie, -attachment=>'foo.gif', -charset=>'utf-7' ); -type: default is 'text/html' -attachment: Instead of displaying the page, some browsers prompt the user to save it to disk. The value of the argument is the suggested name for the saved file. In order for this to work, you may have to set the -type to "application/octet-stream". Most browsers will not cache the output from CGI scripts. Every time the browser reloads the page, the script is invoked anew. You can change this behavior with the -expires parameter. When you specify an absolute or relative expiration interval with this parameter, some browsers and proxy servers will cache the script's output until the indicated expiration date. The following forms are all valid for the -expires field: +30s 30 seconds from now +10m ten minutes from now +1h one hour from now -1d yesterday (i.e. "ASAP!") now immediately +3M in three months +10y in ten years time Thursday, 25-Apr-1999 00:40:33 GMT at the indicated time & date
print $q->redirect('http://somewhere.else/in/movie/land');
$full_url = $q->url(); $full_url = $q->url(-full=>1); #alternative syntax $relative_url = $q->url(-relative=>1); $absolute_url = $q->url(-absolute=>1); $url_with_path = $q->url(-path_info=>1); $url_with_path_and_query = $q->url(-path_info=>1,-query=>1); $netloc = $q->url(-base => 1); url() returns the script's URL in a variety of formats. Called without any arguments, it returns the full form of the URL, including host name and port number http://your.host.com/path/to/script.cgi You can modify this format with the following named arguments: -absolute: If true: /path/to/script.cgi -relative: If true: script.cgi -full: If true: exactly as if called without any arguments -path: If true: append the additional path information to the URL. -query: If true: append the query string to the URL. -base: If true: Generate just the protocol and net location: http://www.foo.com:8000
After creating the HTTP header, most CGI scripts will start writing out an HTML document. The start_html() routine a canned HTML header and the opening <BODY> tag. All parameters are optional. In the named parameter form, recognized parameters are -title, -author, -base, -xbase, -dtd, -lang and -target. Any additional parameters you provide, such as the Netscape unofficial bgcolor attribute, are added to the <BODY> tag. print $q->start_html( -title=>'Secrets of the Pyramids', -author=>'fred@capricorn.org', -base=>'true', -target=>'_blank', -meta=>{'keywords'=>'pharaoh secret mummy', 'copyright'=>'copyright 1996 King Tut'}, -style=>{'src'=>'/styles/style1.css'}, -bgcolor=>'blue' ); -meta results: <META NAME="keywords" CONTENT="pharaoh secret mummy"> <META NAME="copyright" CONTENT="copyright 1996 King Tut"> -head: for creating an HTTP-EQUIV type of <META> tag or other arbitrary HTML elements to the <HEAD> section. For example, to place the <LINK> element in the head section, use this: print start_html( -head=>Link( {-rel=>'next',-href=>'http://www.capricorn.com/s2.html'} ) ); To incorporate multiple HTML elements into the <HEAD> section, just pass an array reference: print start_html( -head=>[ Link({-rel=>'next', -href=>'http://www.capricorn.com/s2.html'}), Link({-rel=>'previous', -href=>'http://www.capricorn.com/s1.html'}) ); To create an HTTP-EQUIV <META> tag: print start_html( -head=>meta({-http_equiv => 'Content-Type', -content=>'text/html'}) );
print $q->end_html This ends an HTML document by printing the </BODY></HTML> tags.
Example: print $q->blockquote( "Many years ago on the island of", $q->a({-href=>"http://crete.org/"},"Crete"), "there lived a Minotaur named", $q->strong("Fred.") ), $q->hr; Result: <blockquote> Many years ago on the island of <a HREF="http://crete.org/">Crete</a> there lived a minotaur named <strong>Fred.</strong> </blockquote> <hr> If you provide one or more string arguments, they are concatenated together with spaces and placed between opening and closing tags: print $q->h1("Chapter","1"); # <H1>Chapter 1</H1>"
One of the cool features of the HTML shortcuts is that they are distributive. If you give them an argument consisting of a reference to a list, the tag will be distributed across each element of the list. Example: print $q->ul( $q->li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) ); Result: <UL> <LI TYPE="disc">Sneezy</LI> <LI TYPE="disc">Doc</LI> <LI TYPE="disc">Sleepy</LI> <LI TYPE="disc">Happy</LI> </UL> Example: print $q->table( {-border=>undef}, $q->caption('When Should You Eat Your Vegetables?'), $q->Tr({-align=>CENTER,-valign=>TOP}, $q->th(['Vegetable', 'Breakfast','Lunch','Dinner']), $q->td(['Tomatoes' , 'no', 'yes', 'yes']), $q->td(['Broccoli' , 'no', 'no', 'yes']), $q->td(['Onions' , 'yes','yes', 'yes']) ) );
comment: comment() generates an HTML comment (<!-- comment -->). Example: print comment('here is my comment'); The following functions begin with initial caps to avoid conflicts with built-in Perl functions: Select, Tr, Link, Delete, Accept, Sub
All HTML that is emitted by the form-generating functions is passed through a function called escapeHTML(): $escaped_string = escapeHTML("unescaped string"); This means that you can safely use "<CLICK ME>" as the label for a button. However, it also interferes with your ability to incorporate special HTML character sequences, such as Á, into your fields. If you wish to turn off automatic escaping, call the autoEscape() method with a false value immediately after creating the CGI object: $q = new CGI; $q->autoEscape(undef); Automatic escaping does not apply to other (non-form) shortcuts such as h1(). You should call escapeHTML() yourself on untrusted data in order to protect your pages against nasty tricks that people may enter into guestbooks, etc.
When you don't want the comma to result in a space, temporarily redefine $" { # this block helps ensure $" isn't changed for subsequent code local($") = ''; print blockquote('fi','sh')); # <BLOCKQUOTE>fish</BLOCKQUOTE> }
Choices: start_form() defaults: method: POST action: this script enctype: application/x-www-form-urlencoded start_multipart_form() # use this version for filefields (safer to always use?) defaults: method: POST action: this script enctype: multipart/form-data endform() # closing </FORM> tag.
print $q->textfield( -name=>'field_name', -default=>'starting value', -size=>50, -maxlength=>80 ); OR print $q->textfield( 'field_name','starting value',50,80 ); Order is important, as second form illustrates. The first param is required; the second, third, fourth are optional.
print $q->textarea( -name=>'foo', -default=>'starting value', -rows=>10, -columns=>50 ); OR print $q->textarea( 'foo','starting value',10,50 ); See textfield() for same requirements.
print $q->password_field( -name=>'secret', -value=>'starting value', -size=>50, -maxlength=>80 ); OR print $q->password_field( 'secret','starting value',50,80 ); See textfield() for same requirements.
print $q->filefield( -name=>'uploaded_file', -default=>'starting value', # Note: ignored! blank result! -size=>50, -maxlength=>80 ); OR print $q->filefield( 'uploaded_file','starting value',50,80 ); To use filefield(), use start_multipart_form(), not start_form(). Parameters: first is required; the rest are optional. You can retrieve the entered filename by calling param(): $filename = $q->param('uploaded_file'); Note: Some browsers return the filename only. Others return the full path to the file, using the path conventions of the user's machine. Regardless, the name returned is always the name of the file on the user's machine. The filename returned is also a file handle. Thus you can use it as in these examples: # Read the lines of a text file and print them out via $_ while (<$filename>) { print; } # SAFER: use upload(). When called with the name of an # upload field, upload() returns a filehandle (or undef if the # parameter is not a valid filehandle). (This is safer because # it is possible for the remote user to type GARBAGE into # the upload field, in which case what you get from param() is # not a filehandle at all, but a string. $fh = $q->upload('uploaded_file'); while (<$fh>) { print; } # Copy a binary file to somewhere safe (this does # not use the SAFE style shown above) open (OUTFILE,">>/usr/local/web/users/feedback"); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; } Additional info uploaded with a file When a file is uploaded the browser usually sends along some information along with it in the format of headers, such as MIME content type. To retrieve this information, call uploadInfo(). It returns a reference to an associative array containing all the document headers. $filename = $q->param('uploaded_file'); $type = $q->uploadInfo($filename)->{'Content-Type'}; unless ($type eq 'text/html') { die "HTML FILES ONLY!"; }
Upon upload error (such as user clicking Stop before upload is finished), CGI.pm returns undef for the name of the uploaded file and sets cgi_error() to the string "400 Bad request (malformed multipart POST)". This example shows the error message incorporated into a status code to be sent to the browser. $file = $q->upload('uploaded_file'); if (!$file && $q->cgi_error) { $errorMsg = $q->cgi_error; print $q->header(-status=>$errorMsg); exit 0; } You are free to create/print a custom HTML page to state the error.
print $q->popup_menu( 'menu_name', ['eenie','meenie','minie'], 'meenie' ); OR %labels = ( 'eenie'=>'your first choice', 'meenie'=>'your second choice', 'minie'=>'your third choice' ); print $q->popup_menu( 'menu_name', ['eenie','meenie','minie'], 'meenie', \%labels ); OR print $q->popup_menu( -name=>'menu_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -labels=>\%labels ); -name: required - values: required; an array reference containing the list of menu items. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as "\@foo". -default: optional; the name of the default menu choice. If not specified, the first item is the default. -labels: optional; a pointer to an associative array containing long user-visible labels for the list items. If not provided, the values will be displayed. The selected value of the popup menu can be retrieved: $popup_menu_value = $q->param('menu_name');
print $q->scrolling_list( 'list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true' ); OR print $q->scrolling_list( 'list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true', \%labels ); OR print $q->scrolling_list( -name=>'list_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -size=>5, -multiple=>'true', -labels=>\%labels ); -name and -values: see popup menu above -default: optional; can be a reference to a list containing the values to be selected by default OR can be a single value to select. If not provided, nothing is initially selected. In the named parameter version, you can use the synonym "-defaults" for this parameter. -size: optional; size of the list -multiple: optional; set to true to allow multiple simultaneous selections -labels: optional; a pointer to an associative array containing long user-visible labels for the list items. If not provided, the values will be displayed. The selected values can be retrieved: @selected = $q->param('list_name');
print $q->checkbox_group( -name=>'group_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -linebreak=>'true', -labels=>\%labels ); OR print $q->checkbox_group( 'group_name', ['eenie','meenie','minie','moe'], ['eenie','moe'], 'true', \%labels ); -name and -values: required; The second argument should be an array reference. -default: optional; it can be either a reference to a list containing the values to be checked by default OR a single value to checked. If missing or undefined, nothing is initially selected. -linebreak: optional; if true, presents options vertically instead of default horizontally. -labels: optional; a pointer to an associative array containing long user-visible labels for the list items. If not provided, the values will be displayed. All checked boxes are returned as a list under the parameter name 'group_name'. The values of the "on" checkboxes can be retrieved with: @turned_on = $q->param('group_name'); The value returned by checkbox_group() is actually an array of button elements. You can capture them and use them within tables, lists, or in other creative ways: @h = $q->checkbox_group( -name=>'group_name', -values=>\@values ); &use_in_creative_way(@h);
print $q->checkbox( -name=>'checkbox_name', -checked=>'checked', -value=>'ON', -label=>'CLICK ME' ); OR print $q->checkbox( 'checkbox_name', 'checked', 'ON', 'CLICK ME' ); checkbox() is used to create an isolated checkbox that is unrelated to any others. -name: required; The required name for the checkbox AND the user-readable label printed next to the checkbox. -checked: optional; checked if true [my massive reword; check] -value: optional; the value of the checkbox when it is checked. If not provided, the word "on" is used. -label: optional; the user-readable label to be attached to the checkbox. If not provided, the checkbox name is used. The value of the checkbox can be retrieved using: $turned_on = $q->param('checkbox_name');
print $q->radio_group( -name=>'group_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -linebreak=>'true', -labels=>\%labels ); OR print $q->radio_group( 'group_name', ['eenie','meenie','minie'], 'meenie', 'true', \%labels ); -name: required -values: required; the list of values for the radio buttons. The values and the labels that appear on the page are identical. Pass an array *reference* in the second argument, either using an anonymous array, as shown, or by referencing a named array as in "\@foo". -default: optional; the name of the default button to turn on. If not specified, the first item will be the default. You can provide a nonexistent button name, such as "-" to start up with no buttons selected. -linebreak: optional; set to true to present the buttons vertically instead of the default horizontally. -labels: optional; a pointer to an associative array containing long user-visible labels for the list items. If not provided, the values will be displayed. The selected radio button can be retrieved: $which_radio_button = $q->param('group_name'); The value returned by radio_group() is an array of button elements. You can capture them and use them within tables, lists, or in other creative ways: @h = $q->radio_group(-name=>'group_name',-values=>\@values); &use_in_creative_way(@h);
print $q->submit( -name=>'button_name', -value=>'value' ); OR print $q->submit('button_name','value'); -name: optional; You can give the button a name if you have several submission buttons in your form and you want to distinguish between them. The name will also be used as the user-visible label. NOTE: A few older browsers don't deal with this correctly and never send back a value from a button. -value: optional; gives the button a value that will be passed to your script in the query string. You can tell which button was pressed by using different values for each one: $which_one = $q->param('button_name');
print $q->reset reset() creates the "reset" button. Restores the form to its value from the last time the script was called, NOT necessarily to the defaults.
print $q->defaults('button_label') When invoked, the button causes the form to be completely reset to its defaults, wiping out all the changes the user ever made.
print $q->hidden( -name=>'hidden_name', -default=>['value1','value2'...] ); OR print $q->hidden( 'hidden_name','value1','value2'... ); Produces a text field that can't be seen by the user. It is useful for passing state variable information from one invocation of the script to the next. -default: required; specifies its value. In the named parameter style of calling, you can provide a single value here or a reference to a whole list
print $q->image_button( -name=>'button_name', -src=>'/source/URL', -align=>'MIDDLE' ); OR print $q->image_button( 'button_name','/source/URL','MIDDLE' ); Produces a clickable image. The position of the click is returned to your script as "button_name.x" and "button_name.y". -align: optional; TOP, BOTTOM or MIDDLE Fetch the value of the button this way: $x = $q->param('button_name.x'); $y = $q->param('button_name.y');
cookie() creates a new cookie. The cookie created by cookie() must be incorporated into the HTTP header within the string returned by the header() method: print $q->header(-cookie=>$my_cookie); $my_cookie = $q->cookie( -name=>'sessionID', -value=>'xyzzy', -expires=>'+1h', -path=>'/cgi-bin/database', -domain=>'.capricorn.org', -secure=>1 ); print $q->header(-cookie=>$cookie); -name: The name of the cookie (required). This can be any string at all. Although browsers limit their cookie names to non-whitespace alphanumeric characters, CGI.pm removes this restriction by escaping and unescaping cookies behind the scenes. -value: The value of the cookie. This can be any scalar value, array reference, or even associative array reference. For example, you can store an entire associative array into a cookie this way: $cookie = $q->cookie( -name=>'family information', -value=>\%childrens_ages ); -path: The optional partial path for which this cookie will be valid. -domain: The optional partial domain for which this cookie will be valid. -expires: The optional expiration date for this cookie. See header() for format. -secure: If true, this cookie will only be used within a secure SSL session.
Request it by name: use CGI; $q = new CGI; $riddle = $q->cookie('riddle_name'); %answers = $q->cookie('answers'); Cookies created with a single scalar value, such as the "riddle_name" cookie, will be returned in that form. Cookies with array and hash values can also be retrieved. The cookie and CGI namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by param() and cookie() are independent of each other. However, it's simple to turn a CGI parameter into a cookie, and vice-versa: # turn a CGI parameter into a cookie $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]); # vice-versa $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
use CGI qw/:standard :html3/; #here's a stylesheet incorporated directly into the page $newStyle=<<END; <!-- P.Tip { margin-right: 50pt; margin-left: 50pt; color: red; } P.Alert { font-size: 30pt; font-family: sans-serif; color: red; } --> END print header(); print start_html( -title=>'CGI with Style', -style=>{ -src=>'http://www.capricorn.com/style/st1.css', -code=>$newStyle } ); print h1('CGI with Style'), p({-class=>'Tip'}, "Better read the cascading style sheet spec " . "before playing with this!"), span({-style=>'color: magenta'}, "Look Mom, no hands!", p(), "Whooo wee!" ); print end_html; Pass an array reference to -style in order to incorporate multiple stylesheets into your document.
The Dump() method produces a string consisting of all the query's name/value pairs formatted nicely as a nested list. This is useful for debugging purposes: print $q->Dump
Some of the more useful environment variables can be fetched through this interface. The methods are as follows: Accept() Return a list of MIME types that the remote browser accepts. If you give this method a single argument corresponding to a MIME type, as in $q->Accept('text/html'), it will return a floating point value corresponding to the browser's preference for this type from 0.0 (don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept list are handled correctly. Note that the capitalization changed between version 2.43 and 2.44 in order to avoid conflict with Perl's accept() function. user_agent() Returns the HTTP_USER_AGENT variable. If you give this method a single argument, it will attempt to pattern match on it, allowing you to do something like $q->user_agent(netscape); remote_user () Return the authorization/verification name used for user verification, if this script is protected. request_method() Returns the method used to access your script, usually one of 'POST', 'GET' or 'HEAD'. content_type() Returns the content_type of data submitted in a POST, generally multipart/form-data or application/x-www-form-urlencoded http() Called with no arguments returns the list of HTTP environment variables, including such things as HTTP_USER_AGENT, HTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the like-named HTTP header fields in the request. Called with the name of an HTTP header field, returns its value. Capitalization and the use of hyphens versus underscores are not significant. For example, all three of these examples are equivalent: $requested_language = $q->http('Accept-language'); $requested_language = $q->http('Accept_language'); $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE'); https() The same as *http()*, but operates on the HTTPS environment variables present when the SSL protocol is in effect. Can be used to determine whether SSL is turned on.
use CGI; $q = new CGI; print $q->header; # this script does not illustrate file upload; thus, # it uses start_html print $q->start_html("Example CGI.pm Form"); print "<H1> Example CGI.pm Form</H1>\n"; &print_prompt($q); &do_work($q); &print_tail; print $q->end_html; sub print_prompt { my($q) = @_; print $q->start_form; print "<EM>What's your name?</EM><BR>"; print $q->textfield('name'); print $q->checkbox('Not my real name'); print "<P><EM>Where can you find English Sparrows?</EM><BR>"; print $q->checkbox_group( -name=>'Sparrow locations', -values=>[England,France,Spain,Asia,Hoboken], -linebreak=>'yes', -defaults=>[England,Asia] ); print "<P><EM>How far can they fly?</EM><BR>", $q->radio_group( -name=>'how far', -values=>['10 ft','1 mile','10 miles','real far'], -default=>'1 mile' ); print "<P><EM>What's your favorite color?</EM> "; print $q->popup_menu( -name=>'Color', -values=>['black','brown','red','yellow'], -default=>'red' ); print $q->hidden('Reference', 'Monty Python and the Holy Grail'); print "<P><EM>What have you got there?</EM><BR>"; print $q->scrolling_list( -name=>'possessions', -values=>['A Coconut','A Grail', 'An Icon','A Sword','A Ticket'], -size=>5, -multiple=>'true' ); print "<P><EM>Any parting comments?</EM><BR>"; print $q->textarea( -name=>'Comments', -rows=>10, -columns=>50 ); print "<P>",$q->reset; print $q->submit('Action','Shout'); print $q->submit('Action','Scream'); print $q->endform; print "<HR>\n"; } sub do_work { my($q) = @_; my(@values,$key); print "<H2>Here are the current settings in this form</H2>"; foreach $key ($q->param) { print "<STRONG>$key</STRONG> -> "; @values = $q->param($key); print join(", ",@values),"<BR>\n"; } } sub print_tail { print <<END; <HR> <ADDRESS>Lincoln D. Stein</ADDRESS><BR> <A HREF="/">Home Page</A> END }
# begin the html page my $htmlTitle = 'Phoon postcard statistics'; my $style =<<END; <!-- BODY, TD { font-size: 10pt; font-family: arial } H4 { font-size: 11pt; } --> END my $charset = 'ISO-8859-1'; if ($lang eq 'jp') { $charset = 'UTF-8'; } my $page = $q->header( -type => 'text/html', -charset=>$charset, ) . $q->start_html( -title=>$htmlTitle, -style=>{ -src=>'/common.css', -code=>$style }, -background=>'/images/phoonback.gif' );