WeasyPrint icon indicating copy to clipboard operation
WeasyPrint copied to clipboard

first image of next page not rendered

Open smilefl0w opened this issue 1 year ago • 5 comments

Hi,

for some reason the first image of a next page of a Label PDF doesn't get rendered. Context: DinA4 Fixed child size of either 70 x 42.3mm or 105 x 42.3 mm for Labels. On pure html the rendering of the images and labels works correctly, only during PDF rendering the issue occurs.

{% load static tailwind_tags %}
<!doctype html>
<html data-theme="light">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" >
        {% load static %}
        {% tailwind_css %}
    
    <title>Document</title>
    <style type="text/css">
        @page  {
            margin: 0;
        }
    </style>
</head>
<body class="font-lato bg-gray-900 flex justify-center">
    <div class="bg-white" style="width:210mm; height:297mm;">
        <div class="flex flex-wrap">
            <!--flex flex-wrap-->
            {% for work in works %}
                <div class="flex items-center justify-center" style="width:{{dimensions.0}}mm; height:{{dimensions.1}}mm; border-left-width: 0px;
                border-right-width: 0px;">
                    <img class="p-2 m-auto" id="image" src="{{ work.image.url }}" alt="image" style="width: 100px; object-fit: contain;">
                    
                    <div id="metadata" class="text-center my-auto p-5 w-full" style="color: rgb(75,85,99); width: 190px; object-fit: contain; font-size: 10px;">
                        <!--INVENTORY NUMBER-->
                        <p class="text-xl mb-1">INV-{{work.inventory_number}}</p>
                        <!--NAME-->
                        {% if work.artist %}
                            <p class="uppercase">{{work.artist.name}}</p>
                        {% else %}
                        <p class="uppercase">{{request.user.first_name}} {{request.user.last_name}}</p>
                        {% endif %}
                        <!--ARTWORK TITLE-->
                        <p class="italic">{{work.title}}</p>
                        <!--DIMENSIONS-->
                        {% if work.width and work.height %}
                            <p class="italic">{{work.width|floatformat}} x {{work.height|floatformat}} {% if work.depth %}x {{work.depth|floatformat}} {% endif %}</p>
                        {% endif %}
                        <!--MATERIALS-->
                        {% if work.materials %}
                            <p>{{work.materials}}</p>
                        {% endif %}

                    </div>
                </div>
            {% endfor %} 
        </div>
    </div> 
</body>
</html>

smilefl0w avatar Feb 13 '24 14:02 smilefl0w

Hi!

Could you please share a full HTML+CSS example, not a template with unknown variables, so that we can reproduce the problem?

liZe avatar Feb 13 '24 14:02 liZe

I am using TailwindCSS, and no custom CSS other than the bits found in the html.


<!doctype html>
<html data-theme="light">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" >
    
    <title>Document</title>
    <style type="text/css">
        @page  {
            margin: 0;
        }
        .flex{
  display: flex;
}
.flex-wrap{
  flex-wrap: wrap;
}
.justify-center{
  justify-content: center;
}
.items-center{
  align-items: center;
}
.p-2{
  padding: 0.5rem;
}
.m-auto{
  margin: auto;
}
.text-center{
  text-align: center;
}
.my-auto{
  margin-top: auto;
  margin-bottom: auto;
}
.w-full{
  width: 100%;
}
.py-5{
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
}
.uppercase{
  text-transform: uppercase;
}
.italic{
  font-style: italic;
}
    </style>
</head>
<body class="font-lato bg-gray-900 flex justify-center">
    <div class="bg-white" style="width:210mm; height:297mm;">
        <div class="flex flex-wrap">
                 <!--Child Item-->
                <div class="flex items-center justify-center" style="width:70mm; height:42.3mm; border-left-width: 0px;
                border-right-width: 0px;">
                    <img class="p-2 m-auto" id="image" src="{{ work.image.url }}" alt="image" style="width: 100px; object-fit: contain;">
                    
                    <div id="metadata" class="text-center my-auto p-5 w-full" style="color: rgb(75,85,99); width: 190px; object-fit: contain; font-size: 10px;">
                        <p class="text-xl mb-1">INV-100</p>
                        <p class="uppercase">Max Mustermann</p>
                        <p class="italic">Basic Artwork</p>
                        <p class="italic">150 x 80 cm</p>
                        <p>Oil on canvas</p>
                    </div>
                </div> <!--Child Item End-->
        </div>
    </div> 
</body>
</html>

I think all styles should be included now. I have not replaced the image variable.

smilefl0w avatar Feb 13 '24 15:02 smilefl0w

I’m sorry, but I don’t understand how your document works.

  • Your body is a flex container with no wrap, so it won’t have more than one line.
  • Your first div has a height set to 297mm.

So, the body has a single line of 297mm-height children, and so will fit on the first page. How do you manage to get a second page?

liZe avatar Feb 13 '24 20:02 liZe

My body centeres the DinA4 page. On that page there is the actual container that holds the content. If I normally loop over my database and create around 15-17 child items, there will be a page break. On the second page the first image will be missing, while every followed child item works correctly again.

But I would be greateful to know a better structure to just loop over my data and display it in 70x42.3mm or 105x42.3 boxes. The result: Screenshot 2024-02-13 230059

Even in case of a cleaned up document structure like this it is still missing the first childs image of the next page:

<!doctype html>
<html data-theme="light">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" >
    
    <title>Document</title>
    <style type="text/css">
        @page  {
            margin: 0;
        }
        .flex{
  display: flex;
}
.flex-wrap{
  flex-wrap: wrap;
}
.justify-center{
  justify-content: center;
}
.items-center{
  align-items: center;
}
.p-2{
  padding: 0.5rem;
}
.m-auto{
  margin: auto;
}
.text-center{
  text-align: center;
}
.my-auto{
  margin-top: auto;
  margin-bottom: auto;
}
.w-full{
  width: 100%;
}
.py-5{
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
}
.uppercase{
  text-transform: uppercase;
}
.italic{
  font-style: italic;
}
    </style>
</head>
<body class="font-lato">
            div class="flex flex-wrap">
                 <!--Child Item-->
                <div class="flex items-center justify-center" style="width:105mm; height:42.3mm; border-left-width: 0px;
                border-right-width: 0px;">
                    <img class="p-2 m-auto" id="image" src="{{ work.image.url }}" alt="image" style="width: 100px; object-fit: contain;">
                    
                    <div id="metadata" class="text-center my-auto p-5 w-full" style="color: rgb(75,85,99); width: 190px; object-fit: contain; font-size: 10px;">
                        <p class="text-xl mb-1">INV-100</p>
                        <p class="uppercase">Max Mustermann</p>
                        <p class="italic">Basic Artwork</p>
                        <p class="italic">150 x 80 cm</p>
                        <p>Oil on canvas</p>
                    </div>
                </div> <!--Child Item End-->
        </div> 
</body>
</html>

smilefl0w avatar Feb 13 '24 21:02 smilefl0w

If I normally loop over my database and create around 15-17 child items, there will be a page break.

I’m sorry, but I can’t reproduce that. Even with a lot of children I don’t get a page break, for the reasons I listed above.

But I would be greateful to know a better structure to just loop over my data and display it in 70x42.3mm boxes.

Until we get a proper support of flex and/or grid, you can use something like:

<style>
  @page { margin: 0 }
  body { font-size: 0; margin: 0 }
  div {
    font-size: 1rem;
    display: inline-block;
    width: 70mm;
    height: 42.3mm;
    box-sizing: border-box;
    border: 1px solid black;
  }
</style>
<body>
  <div>child</div>
  <div>child</div>
  <div>child</div>
  […]
</body>

liZe avatar Feb 13 '24 22:02 liZe

Don’t hesitate to add a comment if we can do anything for you.

liZe avatar Mar 04 '24 21:03 liZe