Skip to content

Scaling for math content in a block element:

Davide P. Cervone edited this page May 28, 2013 · 2 revisions

Hello there,

I have a question regarding a Scaling possibility for math content in a block element:

the class .MathJax_Display is assigned to any block element containing math with the style width:100% - therefore it takes the width value of the parent element, in my case a sidebar with width 400px size.

Sometimes there are equations and formulas which are slightly bigger in width and therefore they overlap.

Now i want to reduze the font-size a bit to decrease the width in a way that the equation is 400px.

First question:

is there a way to achieve this result within mathjax by configuring the scale property dynamically?

And second:

Is it possible to remove the style="width:100%" property to get the real width of the generated element? (I could than start manipulating the width by reducing the font size and checking via jquery if it already fits.)

I already tried it this way but with no luck.

Thanks for your help and best regards stephan c.


Well, one night and here is a (a very dirty hack, but I guess it will work until an other method is provided)

The .MathJax_Display divs get automatically the css attributes width:100%; and position:relative; I removed this by editing the jax/output/HTML- CSS/jax.js (Looking for the second appearance of .MathJax_Display) Afterwards I added the display:table; shrinkwrapping method to .MathJax_Display in the default.js:

styles: { ".MathJax_Display": { 
              display:"table" 
            } 

No I can catch the actual width of the generated math by jquery via:

jQuery('div.MathJax_Display').each(function(i) { 
    var currentwidth = jQuery(this).width(); 
}); 

Hope that helps somebody! stephan c.


Here is an example that implements what I think you are looking for:

<!DOCTYPE html>
<head>
<script type="text/javascript"
  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML">
</script>
</head>
<body>
<div style="width:400px; border: 1px solid black">
This is a div with small width containing math to be scaled to fit it.

<div id="dynamic" style="margin:1em 0; text-align:center">
\(\displaystyle  x+x+x+x+x+x+x+x+x+x+x+x+x+x \)
</div>

</div>

<script>
MathJax.Hub.Queue(function () {
  var math = document.getElementById("dynamic");
  math.style.display = "inline"; var w = math.offsetWidth; math.style.display = "";
  if (w > 400) {math.style.fontSize = Math.floor(400/w * 100)+"%"}
  MathJax.Hub.Queue(["Rerender",MathJax.Hub,math]);
});
</script>
</body>

No modifications are needed to MathJax, and you do not alter the styles for any of MathJax's output. Instead, you use your own DIV around the math to be adjusted (you can use a class to identify this if you want, an use jQuery as in your own example. In order to get the true width of the math, you use in-line mode with \displaystyle instead. Then in your routine that determines the width, you temporarily change the display CSS to inline (so it gets the natural width) and then put it back to block after getting the width. If the width is bigger than the container, you scale your DIV appropriately and then re-render the mathematics using that scale (this step is not absolutely required, but the results will be better if you re-render it).

Note that you will need to have a container whose font-size you can change (since each equation has its own scaling) and you can't use the one produced by MathJax, since that will be removed and replaced by the re-rendering. So using the extra DIV is really necessary and not extra after all. The styling on the div is to replace the margin and centering that the displayed equation would have had, since we use \​(\displaystyle ... \​) rather than \​[...\​].

Finally, this approach will work no matter what rendering mode the user has chosen, whereas solutions based on the MathJax_Display element will only work with HTML-CSS output (the other renderers use different classes for their output). It is best not to hack on the HTML-CSS output itself, since that may change from version to version, and it makes your results not work in NativeMML or SVG output.

In any case, this should point you in the right direction.

Davide


It is better not to edit the HTML-CSS jax.js file directly, but rather
use your configuration to modify it (people using the CDN don't have
access to do that anyway). For example

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  "HTML-CSS": {
    styles: {
      ".MathJax_Display": {
        width: null,
        position: null,
        display: "table"
      }
    }
  }
});
</script>

would remove the width and position values and add the display:table value that you want.

I don't recommend making this change, however, as this will affect not only the math in the sidebar, but all displayed math. I'm not certain what the effect of setting display:table will be in general.

Finally, your approach will only work for HTML-CSS output, not the NativeMML or SVG output, and so if your user selects a different renderer (or if the configuration chooses between NativeMML and HTML-CSS (as most do), then you won't get the rescaling that you want.

So I recommend the example I sent earlier as a better method of handling this.

Davide


Hello Davide,

thanks for your feedback - you are right, modifiying the the js files is bad so I use know the second version - for the first Version I will need a bit more time to implement.

display:table is one of the easiest ways do "shrinkfit" a div so it will not take the width of its parent:

stephan


I put together a test page demonstrating the simplest version of what Davide described -- here is the link:

If you view page source on this, you should be able to see everything you need about using the Rerender call and getting height and width data. The key to this is to use:

<span id="myeqn" style="display:inline-block;width:auto">\​(\displaystyle ... \)</span> 

I put a thin solid red border on the span to highlight what it is doing. I used the CSS display:inline-block setting instead of display:table -- the default display:inline didn't manage the height of the span correctly for this purpose. You also need to have a non- null initial width setting, so width:auto gets things started. The height and width data don't show up until you click a button.

Note that this demonstrates getting height and width data -- what you do with it after that is up to you. ;-)


Hey, thanks for the example!

I will implement it as soon as I can and will give feedback if something is still vague to me - but I think you nailed it with this example :)

best regards
stephan


Here is a modified version of your page.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript"
  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script>
function changeSize(button) {
  var myeqn = document.getElementById('myeqn');
  myeqn.style.fontSize = button.textContent;
  MathJax.Hub.Queue(
    ['Rerender',MathJax.Hub,'myeqn'],
    function () {
      document.getElementById('mylabel').innerHTML =
        'width: '+myeqn.offsetWidth+", height: "+myeqn.offsetHeight;
    }
  );
}
</script>
</head>
<body>
Font size:
<button onclick="changeSize(this)">x-small</button>
<button onclick="changeSize(this)">small</button>
<button onclick="changeSize(this)">medium</button>
<button onclick="changeSize(this)">large</button>
<button onclick="changeSize(this)">x-large</button>
<p id="mylabel"></p>

<span id="myeqn" style="border:thin solid red; display:inline-block;width:auto;">
\(\displaystyle{\int_{-\infty}^\infty e^{-x^2}\, dx=\sqrt{\pi}}\)
</span>

</body>
</html>

I have put the re-rendering and measuring into one function called by all the buttons. The key change, however, is that the looking up of the size really should be part of the queued functions as well, since the rendering may be asynchronous. Since the math has already been rendered once, it is probably true that everything has already been loaded, but it might be that a stretchy delimiter (for example) is at a different size when the math is scaled, and that might require loading a font, which is asynchronous. Or it might be that some other piece of code is listening on the "New Math" signal that will be generated when the math is rerendered, and that IT starts an asynchronous action that you have to wait for. So you really do want to have the size lookup in the queue as well so that you are sure it isn't done until after the math is ready.

The inline-block is also a good choice. I had used inline because only the width was of concern, but inline-block does give you both, as you point out.

Davide


OK, page at my link is updated with your code Davide. Good point about pushing the width/height stuff onto the queue, too. Also clever of you just to use the button's text-content to specify the size, since I was using the same label anyway.

I am noticing that in some contexts, the browser doesn't seem to show much difference between "medium" and "large" (FF10 in Ubuntu I see normal-looking changes, FF10 in Fedora there is no change in height or width and only minor changes in math layout). Is this just because of availability of certain font sizes or something like that?


MathJax tries to match the ex-hight if its fonts to that of the
surrounding font, but it only has pixel-level resolution, so it may be
that MathJax can't resolve the difference between those two sizes in
the default font for your browser. You could try setting

    <body style="font-size:200%">

and see if you get a better difference that way.

Davide


You might try making a div that contains the span and also some text,
and set its font-size (just using the inner span to measure the
mathematics) and see if the text is getting scaled properly (and to
see how well MathJax is matching the text).

Davide


You could try setting

and see if you get a better difference that way.

This made the rest of the text double size, and the initial MathJax display double size, but as soon as I clicked the buttons (which use the "small", "medium", "large", etc. sizes, and which are absolute) the MathJax went back to the sizes I was seeing before -- still not much difference between "medium" and "large".

You might try making a div that contains the span and also some text, and set its font-size

This was a bit more revealing: when I did this, the surrounding text behaved similarly to the MathJax -- the "large" size text font was heavier and a bit wider than the "medium" size, but not significantly taller. I'm sure MathJax is trying to find its size context from a height measurement (since that is the normal way to measure a font), so this would explain why the MathJax isn't changing much. It must be something about the default font settings for this browser, but I couldn't find anything unusual in the preferences.... Nothing that affects MathJax as a whole, to be sure.


You could try setting

and see if you get a better difference that way.

This made the rest of the text double size, and the initial MathJax display double size, but as soon as I clicked the buttons (which use the "small", "medium", "large", etc. sizes, and which are absolute) the MathJax went back to the sizes I was seeing before -- still not much difference between "medium" and "large". OK, I thought they were relative, but I guess not (at least not in
some browsers).

You might try making a div that contains the span and also some text, and set its font-size

This was a bit more revealing: when I did this, the surrounding text behaved similarly to the MathJax -- the "large" size text font was heavier and a bit wider than the "medium" size, but not significantly taller. I'm sure MathJax is trying to find its size context from a height measurement (since that is the normal way to measure a font), so this would explain why the MathJax isn't changing much. It must be something about the default font settings for this browser, but I couldn't find anything unusual in the preferences.... Nothing that affects MathJax as a whole, to be sure. Yes, MathJax tries to match the ex-height of its fonts with that of
the surrounding font. So if the surrounding fonts aren't changing
much, neither will MathJax's.

Davide

Clone this wiki locally