Skip to content

LaTeX: image using width set at 10% renders badly or inconsistently in table cell #13661

@jfbu

Description

@jfbu
Contributor

Describe the bug

I used :width: 10% in a table cell and got unsatisfactory results.

Image

How to Reproduce

===================
 FOO documentation
===================


image in table cell using width at 10%
======================================


+----------------------------+
|                            |
| .. image:: img.png         |
|    :width: 10%             |
|                            |
+----------------------------+


+---+------------------------+
| a | b                      |
+---+------------------------+
| c | .. image:: img.png     |
|   |    :width: 10%         |
|   |                        |
+---+------------------------+

+---+------------------------+
| a | b                      |
+---+------------------------+
| .. image:: img.png         |
|    :width: 10%             |
|                            |
+---+------------------------+

Environment Information

Platform:              darwin;
Python version:        3.13.3 (v3.13.3:6280bb54784, Apr  8 2025, 10:47:54) [Clang 15.0.0 (clang-1500.3.9.4)])
Python implementation: CPython
Sphinx version:        8.3.0+/e1bd9cb38
Docutils version:      0.21.2
Jinja2 version:        3.1.6
Pygments version:      2.19.1

Sphinx extensions

Additional context

Sphinx translates the 10% into 0.100\linewidth. But \linewidth may be zero at some times of processing of tables 1. In the first two cases tabulary fell back to its minium width of 10pt. In the third case (merged cell), Sphinx emitted a varwidth environment wrapper and seemingly \linewidth had a normal interpretation.

Footnotes

  1. it looks as I was going through a state of confusion here. It is not exactly clear what \linewidth is especially when tabulary tries to find dynamically the best choice of column width, but it is not set to zero. Apologies.

Activity

added this to the 8.3.0 milestone on Jun 13, 2025
jfbu

jfbu commented on Jun 13, 2025

@jfbu
ContributorAuthor

Here is what happens if we use \textwidth, not \linewidth:

Image

The fact that the merged cell occupies full width and that the image is aligned left is due to other things (to start with, merged columns hard-code currently left alignment for legacy reasons, a PR should be done).

gmilde

gmilde commented on Jun 14, 2025

@gmilde

The problem is due to using a percentage value for the only non-empty elemnt in an "auto-width" column:

Determining the column width from the content while the content width depends on the column width is impossible. The different backends (HTML browser, LaTeX with code by the Docutils writer, LaTeX with code from the Sphinx writer) use different fallback methods with different results.

A possible fix in the writer would be to detect the situation, resist the temptation to guess, and report a warning.

Basing percentage values on the document-wide \textwidth would be problematic with valid use cases like

=  ===========================
a  b
c  text and image in one cell   

   .. image:: img.png
      :width: 100%
      :height: 1em
      :loading: embed
      
   text and image in one cell         
=  ===========================

The LaTeX output is sub-optimal. Try the HTML output in Docutils or Sphinx.

modified the milestones: 8.3.0, 9.x on Jun 14, 2025
jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

Thanks for feedback. Postponing this to 9.x milestone.

jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

For the record here is with an added

+----------------------------+
|                            |
| .. image:: python-logo.png |
|    :width: 10%             |
|                            |
+----------------------------+

where the file python-logo.png is found at https://github.com/sphinx-doc/sphinx/tree/master/doc/_static and the other used file is the sphinx.png at that location.

HTML:

Image

LaTeX->PDF:

Image

I initially thought only LaTeX would display a small image, but this is not quite the case. So I less feel a sense of urgency here. Why does the python-logo ends up occupying more space in HTML? it may be related to its native dimension being larger. (1920 vs 200 pixels for sphinx.png)

jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

To be completely honest here, I tried out this example and made a number of comments on the premise that \linewidth is a strange beast in table cells (which is not wrong, in view of some manipulations related to it in dark corners of sphinxlatextables.sty which I have rediscovered now), even possible zero, but in fact I may have made here a confusion with \baselineskip which is set to zero in table cells of the l, r, or c types. I will try now to locate my comments of recent times and maybe correct them.

gmilde

gmilde commented on Jun 14, 2025

@gmilde

A collection of different samples with images in tables. Works in Sphinx and Docutils but the output differs (and is sub-optiomal in different ways.

============================
percentage values in a table
============================


image in table cell using width at 10%
--------------------------------------

Table width default (HTML5 "auto", Docutils LaTeX "grid")

+----------------------------+
| .. image:: img.png         |
|    :width: 10%             |
+----------------------------+


+---+------------------------+
| a | b                      |
+---+------------------------+
| c | .. image:: img.png     |
|   |    :width: 10%         |
+---+------------------------+

+---+------------------------+
| a | b                      |
+---+------------------------+
|   |                        |
|   | text and image         |
|   | in one cell            |
|   |                        |
| c | .. image:: img.png     |
|   |    :width: 10%         |
|   |                        |
|   | text and image         |
|   | in one cell            |
|   |                        |
+---+------------------------+

+---+------------------------+
| a | b                      |
+---+------------------------+
| .. image:: img.png         |
|    :width: 10 %            |
+---+------------------------+

Table widths "auto"

.. table::
   :widths: auto

   +----------------------------+
   | .. image:: img.png         |
   |    :width: 10%             |
   +----------------------------+

.. table::
   :widths: auto

   +---+------------------------+
   | a | b                      |
   +---+------------------------+
   | c | .. image:: img.png     |
   |   |    :width: 10%         |
   +---+------------------------+

.. table::
   :widths: auto

   +---+------------------------+
   | a | b                      |
   +---+------------------------+
   |   |                        |
   |   | text and image         |
   |   | in one cell            |
   |   |                        |
   | c | .. image:: img.png     |
   |   |    :width: 10%         |
   |   |                        |
   |   | text and image         |
   |   | in one cell            |
   |   |                        |
   +---+------------------------+

.. table::
   :widths: auto

   +---+------------------------+
   | a | b                      |
   +---+------------------------+
   | .. image:: img.png         |
   |    :width: 10 %            |
   +---+------------------------+


100% wide image in table cell
-----------------------------

Table width default (HTML5 "auto", Docutils LaTeX "grid"):

+-----------------------------+
| .. image:: img.png          |
|    :width: 100%             |
|    :height: 1em             |
+-----------------------------+

=  ===========================
a  b
=  ===========================
c  .. image:: img.png
      :width: 100%
      :height: 1em
=  ===========================

=  ===========================
a  b
c  text and image in one cell

   .. image:: img.png
      :width: 100%
      :height: 1em

   text and image in one cell
=  ===========================

+---+-------------------------+
| a | b                       |
+---+-------------------------+
| .. image:: img.png          |
|    :width: 100%             |
|    :height: 1em             |
+---+-------------------------+

Table width 50%:

.. table::
   :width: 50%

   =  ===========================
   a  b
   =  ===========================
   c  .. image:: img.png
         :width: 100%
         :height: 1em
   =  ===========================

Table widths "grid":

.. table::
   :widths: grid

   =  ===========================
   a  b
   =  ===========================
   c  .. image:: img.png
         :width: 100%
         :height: 1em
   =  ===========================

Table widths: 3 3

.. table::
   :widths: 3 3

   =  ===========================
   a  b
   =  ===========================
   c  .. image:: img.png
         :width: 100%
         :height: 1em
   =  ===========================

Table widths "auto"

.. table::
   :widths: auto

   =  ===========================
   a  b
   =  ===========================
   c  .. image:: img.png
         :width: 100%
         :height: 1em
   =  ===========================

gmilde

gmilde commented on Jun 14, 2025

@gmilde

For the record here is with an added

+----------------------------+
|                            |
| .. image:: python-logo.png |
|    :width: 10%             |
|                            |
+----------------------------+

The column width of this table is determined by its content.

The width of the content should be 10% of the column width.

What result would you expect???

gmilde

gmilde commented on Jun 14, 2025

@gmilde

So we have no notion of "container block" in LaTeX. The only one which comes to mind is the text area.

While I don't know of any way to get the height of a containing element, \linewidth is (in most cases) a suitable dimension for the currently available width.

gmilde

gmilde commented on Jun 14, 2025

@gmilde

Then there is also the fact that PDFs are either printed on paper or viewed on screen. I usually set my PDF viewer to auto-enlarge the view to focus on the contents. And what do PDF viewers propose then? To enlarge the view to the width of the text area, not the paper width.

I use the "evince" PDF viewer, that offers a drop down list for the magnification with "adapt to page", "adapt to width", "auto", "5o%", 70%, ... , 400%.

"adapt to width" fits the paper-width into the viewport. I don't know how to automatically set the magnification to show the text block.

jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

For the record here is with an added

+----------------------------+
|                            |
| .. image:: python-logo.png |
|    :width: 10%             |
|                            |
+----------------------------+

The column width of this table is determined by its content.

The width of the content should be 10% of the column width.

What result would you expect???

I expect 10% of the width of where the table is going to stand. So 10% of text area width. In this manner the 10% means the same things in all cells, even merged ones of the table.

So we have no notion of "container block" in LaTeX. The only one which comes to mind is the text area.

While I don't know of any way to get the height of a containing element, \linewidth is (in most cases) a suitable dimension for the currently available width.

I will remain cautious about what I will say about \linewidth, due to my recent blunders, but, as Sphinx uses for short tables without problematic elements tabulary, it is not all clear what \linewidth will end up being and may differ between first and second pass of tabulary. Also, merged cells use a varwidth environment, so here again it is not at all clear what \linewidth will end up being. I think what most users would (no, should, I am very prejudiced here so "most users" is synonymous with "me") expect that \linewidth refers to the width of the immediate parent of the table, so the \textwidth if at top level. Or the reduced value if in a list or quoted blocks (I progress towards rejoining your view on nested lists).

I understand it could make sense to ask for an image to occupy "half" the width of the cell, if the cell contains some other contents deciding of that width, but in my view, this is really a fringe case.

A weak point of my intuitive interpretation of what % should mean there is that, basically I feel that as the LaTeX output size can not change, something like % makes sense only if having as comparison something absolute, so in effect I am advocating that for PDF output % should have some aspect of absoluteness and all cells of a table independently of their width should interpret % the same.

But don't think I am pushing this too much: nobody ever complained so far so I am anticipating it will not be worthwile to change anything.

I use the "evince" PDF viewer, that offers a drop down list for the magnification with "adapt to page", "adapt to width", "auto", "5o%", 70%, ... , 400%.

"adapt to width" fits the paper-width into the viewport. I don't know how to automatically set the magnification to show the text block.

I confirm what you say, and apologize, but uninteresting details are relegated to a foonote 1.

Footnotes

  1. I am using Skim on macOS but I recently upgraded my hardware and could not on my current hardware re-confirm certain memory impressions which I thought solid for more than a decade. As it stands I do not even find "Fit to width" anymore, only some "Adapter à l'écran" in French which is non-sense because the original was probably "Adapt to window", "écran" meaning "screen" i.e. the total size of my device, and anyhow what it does is as for you to fit paperwidth inside the (unmodified) window, contrarily to what I recalled of "Fit to width". I do not find anywhere in the Skim menubar some "50%" etc... scaling as I was used to see, they have disappeared, the closest I find is via CTRL-click with a pop-up showing options such as "Zoom-in" "Zoom-out" (in French) and I can also do CMD-+ or CMD--.

jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

A collection of different samples with images in tables. Works in Sphinx and Docutils but the output differs (and is sub-optiomal in different ways.

It appears all examples at 100% do work out reasonable in PDF via Sphinx in the sense that the image does occupy 100% of the cell it occupies. The :width: 3 3 gets interpreted as having columns with same width, it is rendered in LaTeX with \begin{tabular}[t]{\X{3}{6}\X{3}{6}} where X{a}{b} with a and b integers assigns (taking into account the tabcolsep) a/b of the total available width, here is the textwidth. The "grid" case renders via \begin{tabular}[t]{\X{1}{28}\X{27}{28}}. The :width: 50% seems to be ignored altogether I don't know off-hand what that :width: 50% is supposed to mean. The rendering uses \begin{tabulary}{\linewidth}[t]{TT}.

jfbu

jfbu commented on Jun 14, 2025

@jfbu
ContributorAuthor

For the examples you provided you can control the looks in the PDF via the conf.py variable latex_table_style. The current default value is ['booktabs', 'colorrows'], and to recover about the same as what had been until some years ago the longtime legacy rendering one should say latex_table_style = ['standard', 'nocolorrows']. Or now that I check, simply ['standard']. Or rather simply latex_table_style = [].

gmilde

gmilde commented on Jun 17, 2025

@gmilde

The column width of this table is determined by its content.
The width of the content should be 10% of the column width.
What result would you expect???

I expect 10% of the width of where the table is going to stand. So 10% of text area width. In this manner the 10% means the same things in all cells, even merged ones of the table.

This is one of several possible valid assumptions.
As a consequence, a width of 100% would always overflow in a table
(similar to 100vw in any normal text).

I understand it could make sense to ask for an image to occupy "half" the width of the cell, if the cell contains some other contents deciding of that width, but in my view, this is really a fringe case.

IMO, setting the width of an element to a percentage of available space is not more "exotic" than setting its width to a percentage of the global text width.

The width of a table cell can also be specified in the rST source as combination of the :width: and :widths: options for the "table", "csv-table" or "list-table" directives. (The "width" of a table seems to be currently ignored by Sphinx-LaTeX but this is a separate issue.)

IMV, the use case that I want an object (table, image, or figure) to be centre-aligned and take 75% of the width of the current text block (be it a paragraph, a quote, a list item or a table cell) is quite common. This is why the CSS standard "invented" the percentage values for sizes.

If 75% in a LaTeX table became 0.75*textwidth we would end up with a lot of inconsistencies. The interpretation in HTML will not change, so the inconsistency would be either between output formats (and Docutils vs. Sphinx) or between tables (may be only auto-width tables) and all other elements that may contain a table, figure, or image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @gmilde@jfbu

        Issue actions

          LaTeX: image using width set at 10% renders badly or inconsistently in table cell · Issue #13661 · sphinx-doc/sphinx