WeasyPrint icon indicating copy to clipboard operation
WeasyPrint copied to clipboard

display flex is breaking UI

Open anuj9196 opened this issue 1 year ago • 3 comments

Using Django with Bootstrap 5 for CSS. Here is the HTML to produce the card design

{% load static %}
<html lang="en">
<head>
    <title>Attempt Response</title>
    <link href="{% static 'pdf_report/assets/css/styles.css' %}" rel="stylesheet">
</head>

<body>
<div class="container">
    
    <div class="card my-3">
        <div class="card-header bg-gradient-light text-dark p-3 d-flex align-items-center justify-content-between">
            <div class="card-title text-bold mb-0 d-flex">
                <div class="me-1">3.</div>
                <div>
                    <div class="question">
                        Select the following that does not affect rate of evaporation?
                    </div>
                    <div class="d-flex">
                        <div class="bg-primary text-xxs text-white px-2 py-1 rounded text-bolder me-1">
                            Subject: Science
                        </div>
                        <div class="bg-primary text-xxs text-white px-2 py-1 rounded text-bolder">
                            Multiple choice
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="card-body p-3">
            <div class="answer-preview">
                <div class="preview-multiple-choice blockquote ps-2 mb-0 py-2 fs-6">
                    <div class="form-check d-flex align-items-center me-2">
                        <input class="form-check-input"
                               disabled=""
                               id="input-iwslt1"
                               type="radio"
                               value="" name="a" checked>
                        <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-iwslt1">
                            Temperature
                        </label>
                    </div>

                    <div class="form-check d-flex align-items-center me-2">
                        <input class="form-check-input"
                               disabled=""
                               id="input-f84gw3"
                               type="radio"
                               value="" name="a">
                        <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-f84gw3">
                            Surface area
                        </label>
                    </div>

                    <div class="form-check d-flex align-items-center me-2">
                        <input class="form-check-input ng-untouched ng-pristine"
                               disabled=""
                               id="input-zy80v2"
                               type="radio"
                               value="">
                        <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-zy80v2">
                            Wind speed
                        </label>
                    </div>

                    <div class="form-check d-flex align-items-center me-2">
                        <input class="form-check-input"
                               disabled=""
                               type="radio">
                        <label class="custom-control-label mb-0 ms-1 mt-1 text-success" for="input-ckk0hk">
                            Insoluble heavy impurities
                        </label>
                    </div>
                </div>

            </div>
        </div>
        <div class="card-footer d-flex justify-content-between align-items-center bg-light py-2">
            <div class="d-flex">
                <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder me-1"> Time Spent: 8 sec.</div>
                <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder me-1"> 1 Attempt</div>
                <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder"> Timeout</div>
            </div>
            <div>

            </div>
        </div>
    </div>
    
</div>
</body>
</html>

and the python code as

template_path = 'template1.html'
template = get_template(template_path)

html = template.render({})

css_file = 'styles.css'

page_css = CSS(
    string='''
    @page {
        size: A4;
        margin: 1cm;
    }'''
)
stylesheets = [page_css]

css = CSS(filename=css_file)
stylesheets.append(css)

pdf_file = HTML(string=html).write_pdf(
    stylesheets=stylesheets, optimize_images=True, jpeg_quality=60, dpi=150
)
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = 'filename="home_page.pdf"'
return response

I'm expecting it to look like the below screenshot

Screenshot 2024-05-25 at 11 48 41 PM

But the pdf rendered has too much space and space breaking. Event text overflowing on longer strings.

response_1_page-0001 (1)

Removing d-flex (display flex), solves a few of the issues.

anuj9196 avatar May 25 '24 18:05 anuj9196

Hi!

Thanks for your report.

Flex support in WeasyPrint is know to be quite bad in many cases, there are many open issues about that 😒. We want to rewrite the whole Flex module, but it would require a lot of time / money that we didn’t find yet, unfortunately. We’re currently quite busy on other topics (including Grid layout 🚀, which is much more solid that Flex), but we hope that we’ll find the resources to solve all these dirty Flex bugs in the future.

liZe avatar May 27 '24 07:05 liZe

Is it possible to supply the actual HTML and CSS for the example?

This may be partially fixed by #2231 but I have no way to test it since I don't have access to your Django/Bootstrap/etc/etc/etc/ setup.

dhdaines avatar Aug 19 '24 01:08 dhdaines

It’s only partially fixed. Here’s a full HTML example:

<html lang="en">
  <head>
    <title>Attempt Response</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
  </head>

  <body>
    <div class="container">
      <div class="card my-3">
        <div class="card-header bg-gradient-light text-dark p-3 d-flex align-items-center justify-content-between">
          <div class="card-title text-bold mb-0 d-flex">
            <div class="me-1">3.</div>
            <div>
              <div class="question">
                Select the following that does not affect rate of evaporation?
              </div>
              <div class="d-flex">
                <div class="bg-primary text-xxs text-white px-2 py-1 rounded text-bolder me-1">
                  Subject: Science
                </div>
                <div class="bg-primary text-xxs text-white px-2 py-1 rounded text-bolder">
                  Multiple choice
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="card-body p-3">
          <div class="answer-preview">
            <div class="preview-multiple-choice blockquote ps-2 mb-0 py-2 fs-6">
              <div class="form-check d-flex align-items-center me-2">
                <input class="form-check-input"
                       disabled=""
                       id="input-iwslt1"
                       type="radio"
                       value="" name="a" checked>
                <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-iwslt1">
                  Temperature
                </label>
              </div>

              <div class="form-check d-flex align-items-center me-2">
                <input class="form-check-input"
                       disabled=""
                       id="input-f84gw3"
                       type="radio"
                       value="" name="a">
                <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-f84gw3">
                  Surface area
                </label>
              </div>

              <div class="form-check d-flex align-items-center me-2">
                <input class="form-check-input ng-untouched ng-pristine"
                       disabled=""
                       id="input-zy80v2"
                       type="radio"
                       value="">
                <label class="custom-control-label mb-0 ms-1 mt-1 text-" for="input-zy80v2">
                  Wind speed
                </label>
              </div>

              <div class="form-check d-flex align-items-center me-2">
                <input class="form-check-input"
                       disabled=""
                       type="radio">
                <label class="custom-control-label mb-0 ms-1 mt-1 text-success" for="input-ckk0hk">
                  Insoluble heavy impurities
                </label>
              </div>
            </div>

          </div>
        </div>
        <div class="card-footer d-flex justify-content-between align-items-center bg-light py-2">
          <div class="d-flex">
            <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder me-1"> Time Spent: 8 sec.</div>
            <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder me-1"> 1 Attempt</div>
            <div class="bg-dark text-xxs text-white px-2 py-1 rounded text-bolder"> Timeout</div>
          </div>
          <div>

          </div>
        </div>
      </div>
    </div>
  </body>
</html>

liZe avatar Aug 24 '24 21:08 liZe

We’re almost done with this issue! The only problem left is the width of the radio buttons.

Image

(For the record: the numbers transformed into emojis are caused by the font names with "emoji" in the --bs-font-sans-serif variable. I have the same problem with some, but not all, browsers on my system, because Fontconfig is configured to use colored emojis if possible.)

liZe avatar Feb 08 '25 13:02 liZe

Bug is closed and tested in the flex branch, see https://github.com/Kozea/WeasyPrint/issues/2362.

liZe avatar Feb 08 '25 22:02 liZe