Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can we solve \tag overlap with flexboxes? #3066

Open
3 tasks done
ig-perez opened this issue Jun 6, 2021 · 9 comments
Open
3 tasks done

Can we solve \tag overlap with flexboxes? #3066

ig-perez opened this issue Jun 6, 2021 · 9 comments

Comments

@ig-perez
Copy link

ig-perez commented Jun 6, 2021

Before reporting a bug

Nota bene: Please forgive me if my ignorance in Katex internals is making me propose something dumb.

Describe the bug:
Hi guys, thanks for maintaining this package!

As you can imagine for the tittle of this issue I'm struggling with the \tag overlap when displaying web pages in mobile devices. For example this equation:
image

I was trying to solve this by overriding the CSS with this:

    .katex-html {
      display: flex !important;
      flex-direction: row;
      flex-wrap: nowrap;
      justify-content: space-between;
      align-items: baseline;
      overflow-x: auto;
    }

    .katex-html .base {
      display: inline !important;
    }

    .katex-html .tag {
      display: inline !important;
      position: relative !important;
      margin-left: var(--margin-small);
    }

And it works!:
image
image

Sadly, the inline math expressions break:
Before:
image

After:
image

I think it is because both, the inline and block styling, share the same CSS classes. So I want to ask you, what if you use a different CSS class for inline and block styling?

If we have different classes, we can leave inline styling as it is and use the code snippet above just for block equations.

Actually, it might be possible to just add an extra class indicator when inserting a block element, something like katex-blockat the end of the span class property, like this:

image

In this way katex-blockwill have the CSS code snnipet above.

(La)TeX code:
The code of (La)TeX you tried to render:

$$
\begin{aligned}
J(\theta) = - \frac{1}{T} \log L(\theta) = - \frac{1}{T} \sum_{t=1}^{T} \sum_{-m \leq j \leq m} \log P(w_{t+j} | w_t; \theta); j \neq 0
\tag{2}
\end{aligned}
$$

Expected behavior:
The equation number should appear at the right of the equation, not over it.

Environment (please complete the following information):

  • KaTeX Version: 0.13.11
  • Device: Android Mobile device. Can also be shown with Firefox's Responsive Design Mode
  • OS: Android, Linux
  • Browser: Firefox 88.0.1 (64-bit), Chromium Version 90.0.4430.212 (Developer Build) Fedora Project (64-bit)

Thanks!

@ig-perez ig-perez added the bug label Jun 6, 2021
@edemaine
Copy link
Member

edemaine commented Jun 7, 2021

The reason we use the layout we do is that flexbox (as far as I know) cannot center the equation itself; rather, it can only center the equation within the space leftover by the tag. The plus side is that

$$ x=5 $$
\begin{equation} y=5 \end{equation}

is properly aligned. The downside is that the tag can overlap. It would be great to fix the latter without breaking the former.

You probably want to prefix your CSS rules with .katex-display, as in .katex-display .katex-html { ..., so that they apply only to display equations. Perhaps something like this would be worth adding to our CSS customization documentation.

@edemaine edemaine removed the bug label Jun 7, 2021
@ig-perez
Copy link
Author

Hi @edemaine thanks for your reply. I guess a flexbox can center both. I'd love to make some tests as soon as I have some free time. The flexbox is applied over the katex-htmlclass which has two children, baseand tag. The property justify-content: space-between; will use the available width to place both items evenly separated:

image

I guess it is also possible to center the entire flexbox (katex-html) containing both items using margins.

I can not prefix my CSS rules because there is no way to differentiate between the inline equations and block equations (I'm talking about CSS path here). That's why I was suggesting to add an extra CSS class when rendering block equations.

What do you think?

@edemaine
Copy link
Member

justify-content: space-between is incorrect compared to LaTeX behavior, unless we make an invisible tag on the left that has the same width as the visible tag on the right (or vice versa if fleqno is on). For proper LaTeX behavior, the equation part needs to be centered on the line, ignoring the tag. An invisible tag on the left might be a solution, though...

.katex-display is a parent only for block equations. Inline equations don't get that div. Hence prefixing with .katex-display makes those rules only apply to block equations (what's called "display equations" in LaTeX).

@edemaine
Copy link
Member

I tried getting the correct layout with flexbox (for the nth time), using an invisible tag on the left (.antitag) to balance out the tag on the right. Here's my attempt.

Sadly, this doesn't work in the case where the left antitag + equation fit, but the right tag doesn't fit. It works when just the equation fits, or when all three fit, but not when two out of three fit. (To test, try resizing the window.) I don't see how to fix this in all three cases, but I'm open to ideas!

@mbourne
Copy link

mbourne commented Dec 4, 2021

I'm no doubt missing something major, but this fork of your pen appears to work: https://codepen.io/mbourne/pen/KKXdXem

I commented out flex-wrap and justify-content and it gave me what I believe is wanted at all generally-used screen widths.

My "overflowXauto" class is to make the horizontal scroll bar more noticeable than browser defaults.

@edemaine
Copy link
Member

edemaine commented Dec 5, 2021

@mbourne Ah, good point: If we ignore the desire for the equation number to wrap when the width is small, we can at least get the tag not to overlap the equation (but still cause overflow). This is almost certainly an improvement over the current behavior, though still not perfect. (For me, perfect would include: if the screen is wide enough to fix the equation and not the tag, put the tag on a second line, and avoid overflow scrollbars. I imagine this could be fixed with some JavaScript though...)

@mbourne
Copy link

mbourne commented Dec 6, 2021

"... I imagine this could be fixed with some JavaScript though..."

Always best to try to solve things with CSS, but there comes a point...

I'm not a fan of adding any more DOM elements than necessary, so here are 2 attempts that do not use an empty tag.

(1) No wrap case

This addresses the issues of :

  1. No overlap of the equation by the tag
  2. Avoiding scrollbars as much as possible

It's acceptable, I feel, even though it is a little odd right on the crossover between normal and when the scroll bar is about to appear (as you reduce screen width). But 99.99% of users don't resize the browser frantically on each page load - only developers.

Here is an example page: https://bourne2learn.com/math/katex/tag-placement_nowrap.html

My basic approach is to change the tag display to inline-block when the width of the equation and the tag means it's going to overflow. I allow for an imaginary tag width (without actually inserting an imaginary tag) to keep the equation in the middle as much as possible.

The tweak to the equation width in the if statement (1.1*eqnWidth) is to ensure some space between the equation and the tag.

(2) Wrap case

It does make sense to try to wrap the tag (and to attempt your definition of 'perfect' for this), so I gave it a go.

This time, I set the display of the equation to inline-block, and the white-space property of the parent (of the equation and the tag) to normal.

It works reasonably well: https://bourne2learn.com/math/katex/tag-placement_wrap.html

But it gave issues and was a lot more involved. I needed to mess with the .vlist heights and it was becoming ugly quickly.

At certain screen widths, and in certain contexts, the reader may think the tag number is the answer for the equation:

image

The other thing is the tag stays in whatever position it is on page load, so it can be in an odd place when the user scrolls the whole thing horizontally if horizontal scrolling is required at load:

image

This could be fixed by pulling the tag out of the whole span.katex and placing it below the equation and aligning it right. This would allow the equation to be scrolled left-right, while leaving the tag in place. I'll leave this as an exercise for the reader :p

Hopefully one or other approach is useful.

@rupumped
Copy link

rupumped commented Mar 5, 2023

Thank you, @mbourne! For those of you wanting a quick way to implement their solution in your own work, including the following in the <head> works for me:

<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js" integrity="sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4" crossorigin="anonymous"></script>
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
  <script>
    function adjustTag() {
	    var browserWidth = document.querySelector('body').clientWidth;
	    var eqnWidth = 0;
	    var tagWidth = 0;
    
	    var tags = document.querySelectorAll('.katex-html .tag');	
	    
	    for(i=0;i<tags.length;i++) {
		    eqnWidth = tags[i].parentNode.querySelector('.base').offsetWidth;
		    tagWidth = tags[i].clientWidth;
		    
		    tags[i].style.border = "";
		    
		    if(1.1*eqnWidth + 2*tagWidth > browserWidth) {
			    tags[i].style.display = "inline-block";
			    tags[i].style.marginLeft = "8px";
			    tags[i].style.position = "static";
		    } else {
			    tags[i].style.background = "";
			    tags[i].style.position = "absolute";
			    tags[i].style.right = 0;
		    }
	    }
    }
    
    function waitKaTeX() {
	    if(document.querySelectorAll('.katex-html').length == 0 ) {
		    requestAnimationFrame(waitKaTeX);
	    } else {
		    cancelAnimationFrame(raf);
		    adjustTag();
	    }
    }
    var raf = window.requestAnimationFrame(waitKaTeX);
    
    window.addEventListener("resize", adjustTag);
  </script>
  <style type="text/css">
    .katex-display > .katex > .katex-html {
        width: 100%;
        position:relative;
    }
    .tag {
        position:absolute;
        right:0; 
    }
    .equation{
        display:block;
        height:auto;
        margin:1em 0;
        padding:0 2px 12px;
        overflow-x:auto;
        white-space:nowrap;
    }
    .equation::-webkit-scrollbar{
        height:8px;
    }
    .equation::-webkit-scrollbar-track{
        -webkit-box-shadow:inset 0 0 4px rgba(0,0,0,0.3);
        border-radius:7px;
    }
    .equation::-webkit-scrollbar-thumb{
        border-radius:7px;
        -webkit-box-shadow:inset 0 0 8px rgba(0,0,0,0.5);
    }
    .equation::-webkit-scrollbar-thumb:hover{
        -webkit-box-shadow:inset 0 0 4px rgba(0,0,0,0.8);
    }
  </style>
</head>

Then, you can write your equations like this in <body>:

<body>
  <div class="equation">
    \begin{equation}
    \mathrm{P}=i^2\mathrm{R}
    \end{equation}
  </div>
</body>

@robertwenink
Copy link

robertwenink commented Sep 19, 2023

Hi,

The following css overrides work for me to make a long equation scroll horizontally and have its tag floated to the right side.

.katex-html {
    overflow-x: auto;
    overflow-y: hidden;
    padding: 3px;
    .base {
      margin: 0 auto;
    }
}

.katex-html:has(span.tag) {
  display: flex !important;
}

.katex-display>.katex>.katex-html>.tag { 
  position: relative !important;
  float: right; 
  margin-left: 0.25rem;
}

Using the :has css function we can recognise if the .katex-html element contains an inline equation or not by checking if a .tag is present. This :has function is not yet available on firefox, where the above css makes the tag still skip a line, but I can live with that. For all other browsers, this solution works (see here).

Mihonarium added a commit to Mihonarium/nanosystems that referenced this issue Apr 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants