This is an issue of the optimizer.
To avoid the miniffier to remove the whitespaces, group the affected element with parenthesis. That workarrounds the issue.
margin-left: calc((50%) - 480px);
Question
I have css statements like this:
margin-left: calc(50% - 480px);
Which work fine unminified but as soon as I begin minifying, the statement gets changed to:
margin-left: calc(50%- 480px);
Rendering all calc statements broken. Similar things happen with width, max-width, min-width, etc. Is there any way I can change the behavior of the bundle to leave those CSS properties alone?
Currently I'm just using bundles.Add(new Bundle())
to prevent minification entirely, but it would be nice if I could minify correctly.
Solution
This is an issue of the optimizer.
To avoid the miniffier to remove the whitespaces, group the affected element with parenthesis. That workarrounds the issue.
margin-left: calc((50%) - 480px);
OTHER TIPS
In addition to the answer above: if you use:
margin-left: calc((50%) + 480px);
You should rewrite it as:
margin-left: calc((50%) - -480px);
Since it didn't seem to fix (50%)+ for me.
If the default css minification is not doing what you need, you can always use a third party one.
bundling allows you to use your own transformations using IBundleTransform
var bundle = new Bundle("~/Content/css", myCustomCssTransform);
there are many different bundlers - nuget
for example you could use YUI compressor:
using System.IO;
using System.Web.Optimization;
using Yahoo.Yui.Compressor;
namespace Bundler.Utilities
{
public enum contentType
{
javascript,
css
}
public class YUITransform : IBundleTransform
{
readonly string _contentType = string.Empty;
public YUITransform(contentType contentType)
{
if (contentType == contentType.css)
{
this._contentType = "text/css";
}
else
{
this._contentType = "text/javascript";
}
}
public void Process(BundleContext context, BundleResponse bundle)
{
bundle.ContentType = this._contentType;
string content = string.Empty;
foreach (FileInfo file in bundle.Files)
{
using (StreamReader fileReader = new
StreamReader(file.FullName)) {
content += fileReader.ReadToEnd();
fileReader.Close();
}
}
bundle.Content = Compress(content);
}
string Compress(string content) {
if (_contentType == "text/javascript")
{
return JavaScriptCompressor.Compress(content);
}
else
{
return CssCompressor.Compress(content,
CssCompressionType.StockYuiCompressor
);
}
}
}
}
This is totally normal as referring to CSS Values and Units Module it states
The following features are at-risk and may be dropped during the CR period: ‘calc()’, ‘toggle()’, ‘attr()’."
If you could skip the spaces there, that wouldn't be a complete minifying. An option is replacing spaces with unicode caracter \00A0
No idea why but calc((50%) - 480px) didnt work for me, however the following worked:
subtraction:
margin-left: calc(((100%) - (480px)))
addition:
margin-left: calc((100%) - -480px)
Beware of using variables in calc. You can end up with another CssMinify() bug:
@myVariable: 0em;
margin-left: calc((50%) - @myVariable);
is compressed and unit is cut off:
margin-left: calc((50%) - 0);
and it is not valid calc() call too!
It seems the issue has been fixed in the version 2.4.9 of YUI Compressor, which can be accessed from here https://mvnrepository.com/artifact/com.yahoo.platform.yui/yuicompressor?repo=bsi-business-systems-integration-ag-scout. I have used this css file:
body{
font-size: calc(50% - 3px);
font-size: calc(50% + 3px);
font-size: calc(50% + +3px);
font-size: calc((50%) + (3px));
font-size: calc(50% + (+3px));
font-size: calc(50% + (3px));
font-size: calc(50% - (-3px));
font-size: calc(50% - -3px);
}
and running this command:
java -jar yuicompressor-2.4.9-BSI-2.jar --line-break 0 -o process.css.min.gz file.css
generates this output, which looks good:
body{font-size:calc(50% - 3px);font-size:calc(50% + 3px);font-size:calc(50% + +3px);font-size:calc((50%)+(3px));font-size:calc(50% + (+3px));font-size:calc(50% + (3px));font-size:calc(50% - (-3px));font-size:calc(50% - -3px)}