What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Put the CSS text in a Java String, wrap it in a <style> element in the HTML String, and pass the combined HTML to your PDF converter. With iText pdfHTML, set a base URI when the document uses relative images, fonts, or stylesheets, then convert the HTML string to an output stream.

Inject a CSS string into HTML before conversion

The most portable approach is to build a complete HTML document and place the stylesheet in its <head>. This keeps the CSS in the same input that the renderer parses and avoids depending on a separate file.

import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.ConverterProperties;

import java.io.FileOutputStream;
import java.io.OutputStream;

public class HtmlToPdf {
    public static void main(String[] args) throws Exception {
        String css = "body { font-family: sans-serif; margin: 24px; }"
                + "h1 { color: #245; font-size: 24px; }"
                + "p { line-height: 1.5; }";

        String html = "<!doctype html>"
                + "<html><head>"
                + "<meta charset="UTF-8">"
                + "<style>" + css + "</style>"
                + "</head><body>"
                + "<h1>Report</h1>"
                + "<p>Content generated by Java.</p>"
                + "</body></html>";

        ConverterProperties properties = new ConverterProperties();
        // Set this when relative assets must be resolved.
        properties.setBaseUri("/path/to/document-directory/");

        try (OutputStream out = new FileOutputStream("out.pdf")) {
            HtmlConverter.convertToPdf(html, out, properties);
        }
    }
}

The pdfHTML API includes a convertToPdf(String html, OutputStream pdfStream, ConverterProperties converterProperties) overload, so no temporary HTML file is required. The HTML string must contain valid markup around the injected style. If the CSS comes from a user or another external system, validate and constrain it before inserting it; CSS is not a substitute for sanitizing untrusted HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build the HTML safely

Keep the style element in the head

Place the style element after the character-set declaration and before the body. A Java text block can make larger templates easier to read when your project uses a Java version that supports them:

String css = """
        body { color: #222; }
        .total { font-weight: 700; border-top: 1px solid #999; }
        @page { margin: 18mm; }
        """;

String html = """
        <!doctype html>
        <html>
          <head>
            <meta charset="UTF-8">
            <style>%s</style>
          </head>
          <body>
            <div class="total">Total: 125.00</div>
          </body>
        </html>
        """.formatted(css);

When concatenating ordinary strings, ensure that the CSS does not accidentally remove the closing </style> tag or introduce malformed markup. If values are inserted into the HTML, escape them for HTML first. A CSS value and an HTML text node require different escaping rules.

Use a base URI for relative resources

A stylesheet embedded in the HTML does not automatically tell the converter where to find relative resources. Set ConverterProperties.setBaseUri(...) to the directory or URL that should be treated as the document’s parent location. This matters for references such as:

body {
    background-image: url("images/watermark.png");
}

The same base URI helps resolve relative image URLs, fonts, and linked stylesheets. Without it, a document may convert successfully while silently omitting those assets. Prefer an absolute, controlled directory or URL and make sure the Java process has permission to read it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When the CSS is in a separate string or file

Inline the complete string

If your application receives CSS from a database, a template service, or a file read into memory, the final operation is unchanged: append it between an opening and closing <style> tag before calling HtmlConverter.convertToPdf. You can combine multiple strings, but keep a predictable order because later declarations can override earlier ones.

String reset = "* { box-sizing: border-box; }";
String theme = ".accent { color: #245; }";
String css = reset + "n" + theme;
String html = "<html><head><style>"
        + css
        + "</style></head><body>...</body></html>";

Linking a stylesheet instead

You may use a <link rel="stylesheet" href="..."> element when the stylesheet is available at a stable location. The href is then resolved relative to the configured base URI. Inline CSS is usually simpler for a self-contained report, while a linked file is easier to cache and maintain across many templates.

Why CSS is ignored in the generated PDF

The converter is not a browser

HTML-to-PDF engines implement different subsets of HTML and CSS. iText describes pdfHTML as an HTML/CSS-to-PDF converter with HTML5 and CSS3 support, but individual features still have documented limitations. Check the official pdfHTML supported and unsupported feature reference before depending on advanced layout, animation, scripting, or browser-specific behavior.

OpenHTMLtoPDF is another pure-Java option. Its documentation describes rendering a reasonable subset of well-formed XML/XHTML and some HTML5 using CSS 2.1 and later standards. It is therefore important to write standards-oriented markup and verify the exact renderer you deploy rather than assuming that a declaration supported by Chrome will work in the PDF.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common markup and cascade problems

  • Malformed HTML: close elements, quote attributes, and include a single coherent document structure.
  • Selector mismatch: confirm that the class or element named in CSS exists in the generated HTML and that a later rule is not overriding it.
  • Unsupported feature: replace browser-only features with a layout supported by your converter, or consult its feature matrix.
  • Missing assets: set a base URI and use readable paths for images and fonts.
  • Encoding errors: declare UTF-8 and pass Java strings without converting them through a platform-default character set.

Legacy iText 5 XML Worker: parse CSS through a resolver

XML Worker uses a different pipeline from pdfHTML. You do not normally solve a CSS string by placing it in a pdfHTML call. Instead, turn the CSS text into a stream, create a CssFile, add it to a StyleAttrCSSResolver, and put that resolver in the CssResolverPipeline before parsing the HTML.

String cssText = "body { font-family: Helvetica; } h1 { color: #245; }";
String htmlText = "<html><head></head><body>"
        + "<h1>Report</h1></body></html>";

CSSResolver cssResolver = XMLWorkerHelper.getInstance()
        .getDefaultCssResolver(false);
try (InputStream cssStream = new ByteArrayInputStream(
        cssText.getBytes(StandardCharsets.UTF_8))) {
    CssFile cssFile = XMLWorkerHelper.getCSS(cssStream);
    cssResolver.addCss(cssFile);

    HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);

    XMLWorker worker = new XMLWorker(pipeline, true);
    XMLParser parser = new XMLParser(worker);
    parser.parse(new ByteArrayInputStream(
            htmlText.getBytes(StandardCharsets.UTF_8)));
}

The exact surrounding document and writer setup depends on your XML Worker application, but the important sequence is the CSS byte or character stream, XMLWorkerHelper.getCSS, cssResolver.addCss, and the resolver pipeline. XML Worker is a legacy approach; for new development, evaluate pdfHTML or another maintained renderer.

Choose a renderer deliberately

Concern iText pdfHTML OpenHTMLtoPDF Why it matters
Input model HTML string and converter properties Well-formed XML/XHTML and some HTML5 Your template may need cleanup before rendering.
CSS coverage HTML5/CSS3-oriented support with feature-specific limits CSS 2.1 and later standards, within its documented subset Check support for every advanced declaration you rely on.
Resources Base URI and converter configuration resolve images, fonts, and stylesheets Configure resource access according to the library’s APIs Relative paths are a frequent cause of missing output.
Output requirements Supports HTML/CSS-to-PDF workflows and PDF-related options Outputs PDF or images Accessibility, PDF/A, and other standards need separate verification.
Maintenance Use current pdfHTML documentation and feature tables Use the project documentation for its supported subset Version changes can alter layout or feature behavior.

Licensing is also a project-level decision. Review the license and commercial terms for the exact version you deploy; they are not interchangeable between renderers.

Production checklist

  • Generate a complete HTML document with a UTF-8 declaration.
  • Insert the CSS string inside one or more valid <style> elements.
  • Use deterministic class names and inspect the final HTML string when debugging.
  • Set a base URI whenever any URL is relative.
  • Bundle or explicitly permit required fonts and images.
  • Test the PDF with the renderer version used in production, not only in a browser.
  • Verify page breaks, margins, tables, long words, missing glyphs, and very long documents.
  • Keep CSS size reasonable; huge generated stylesheets increase parsing and memory work.
  • Close output streams and surface conversion exceptions instead of returning a partially written file.

Troubleshooting by symptom

The PDF is unstyled

Log the final HTML string and confirm that the <style> element contains the expected text. Check for an unclosed tag, a selector that does not match, or CSS syntax that the renderer cannot parse. If you use XML Worker, verify that the CSS resolver was added to the pipeline before parsing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Images or fonts disappear

Set baseUri to the correct parent directory or URL, then test the resolved path from the same account that runs Java. Use a known-good absolute resource temporarily to distinguish a path problem from an unsupported format or permission problem.

Only some declarations work

Compare the declaration with the renderer’s supported-feature documentation. Simplify flex, grid, positioning, or other advanced layout into supported constructs where necessary. Also inspect the cascade: an inline style or later rule may be winning.

Non-ASCII characters are wrong

Keep the HTML declaration at UTF-8 and create byte streams explicitly with StandardCharsets.UTF_8. A missing font can still produce blank boxes even when the text encoding is correct, so configure a font that contains the required glyphs.

Conversion fails or times out

Reduce the input to a minimal document, then add styles and assets back in stages. A malformed fragment, inaccessible remote resource, or unsupported construct can be isolated this way. For large reports, split data generation from conversion, avoid repeatedly rebuilding identical CSS, and monitor heap use; the complete HTML and PDF may both be in memory during parts of the operation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost considerations

Inlining a CSS string removes a filesystem lookup, but it does not eliminate the work of parsing CSS and laying out every page. Reuse a template and static stylesheet where possible, while still producing a fresh document for each request. Cache immutable images or fonts at the application layer when your renderer permits it. For untrusted URLs, restrict network and file access so conversion cannot read arbitrary local files.

Render a representative sample before release: short and multi-page documents, long tables, missing optional fields, right-to-left or accented text when applicable, and pages containing the largest images. Compare the resulting PDFs after library upgrades because layout differences can be version-specific. iText’s API reference and tutorial document the String overload and base-URI configuration; its feature reference is the authority for individual CSS support.

Or skip the browser setup

If your real requirement is a clean image or PDF capture of a web page rather than server-side HTML-to-PDF rendering, ScreenshotNeo provides a single HTTP endpoint and an MCP server for AI agents. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

For a direct request, see the ScreenshotNeo API documentation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

It also supports PNG, JPEG, WebP, and PDF output, full-page and element captures, custom CSS and JavaScript, waiting rules, headers and cookies, device and viewport settings, and asynchronous jobs. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account to get started.

Frequently asked questions

Can CSS remain in a Java variable until conversion?

Yes. The converter only needs the final HTML string to contain the style element when conversion starts; the CSS does not need to exist as a physical file.

Do I need a base URI for inline CSS?

Not for declarations that contain no relative URLs. You do need one when the HTML or CSS refers to relative images, fonts, or linked stylesheets.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should new projects use XML Worker?

XML Worker is legacy. For a new project, compare a maintained renderer such as pdfHTML or OpenHTMLtoPDF against your HTML, CSS, licensing, and PDF requirements.

Why does browser preview differ from the PDF?

A browser and a PDF renderer implement different HTML/CSS subsets and pagination models. Validate the exact renderer and version you ship, and replace unsupported browser-only techniques.

Frequently Asked Questions

Can CSS remain in a Java variable until conversion?

Yes. The converter only needs the final HTML string to contain the style element when conversion starts; the CSS does not need to exist as a physical file.

Do I need a base URI for inline CSS?

Not for declarations that contain no relative URLs. You do need one when the HTML or CSS refers to relative images, fonts, or linked stylesheets.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should new projects use XML Worker?

XML Worker is legacy. For a new project, compare a maintained renderer such as pdfHTML or OpenHTMLtoPDF against your HTML, CSS, licensing, and PDF requirements.

Why does browser preview differ from the PDF?

A browser and a PDF renderer implement different HTML/CSS subsets and pagination models. Validate the exact renderer and version you ship, and replace unsupported browser-only techniques.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.