10

I am using jquery UI datepicker against a div so I can see the months on my screen. The issue is that it seems to add a width attribute that is much wider than it actually needs which creates this extra white space as seen below

enter image description here

here is my code:

HTML

<div id="myCalendar"></div>

Javascript:

 $("#myCalendar").datepicker({
      numberOfMonths: 6,
      showButtonPanel: false,
       beforeShowDay: function (date) {

           var dateString = $.datepicker.formatDate('yy-mm-dd', date);
           if ($.inArray(dateString, highlightDateArray) > -1)
           {
               return [true, "highlightCell", ''];
           }
               else 
           {
               return [true, '', ''];
           }
        }
    });

from looking in firebug, I see

element.style {
     display: block;
     width: 102em;
}

which is way longer than necessary (having it at 82em; would be fine)

What is the best way of eliminating this white space?

leora
  • 188,729
  • 360
  • 878
  • 1,366
  • 1
    That is how `display:block;` works. `display:block` gives the element a 100% width to make sure that no other element can be placed next to it, so the next element will be placed below the object. I asked this question to and here is the solution: http://stackoverflow.com/questions/29515601/why-has-my-link-an-infinite-width – Vinc199789 Jul 18 '15 at 12:23
  • I understand the display:block point but my issue is more about the datepicker is putting this style inline so i don't see any css classses, etc to overwrite – leora Jul 18 '15 at 12:51
  • Jquery UI is changing a lot when you activate it. What you can do (I tested it) is going to jquery ui and inspect the datepicker with element inspect. With element inspect can you for example see that each day has the selector `.ui-datepicker td`. by doing this you can find the classes and selectors you need and than you should be able to overwrite the style. – Vinc199789 Jul 18 '15 at 13:30

2 Answers2

7

The issue is that it seems to add a width attribute that is much wider than it actually needs which creates this extra white space..

Reason:

This is the way jQuery UI has been designed.

  1. It uses a magic number 17 to calculate the width of the container.

From the code of jquery UI v1.11.4 js at line numbers 4561 thru 4574:

var origyearshtml,
    numMonths = this._getNumberOfMonths(inst),
    cols = numMonths[1],
    width = 17,
    activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );

if ( activeCell.length > 0 ) {
    datepicker_handleMouseover.apply( activeCell.get( 0 ) );
}

inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
if (cols > 1) {
    inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
}

It checks if the number of columns (months to show) are more than 1, and calculates the width as (17 * cols) + 'em'.

  1. Rest is taken care of by the core CSS. There are styles ui-datepicker-multi-2 thru to ui-datepicker-multi-4 which have predefined width in %. This causes the inner .ui-datepicker-group to fit within the width calculated in the Javascript code and applied in the same line (see js code above). If you see the core CSS, you will find that it is styled only for only upto 4 months across. If the number of months exceed 4, then the width is not applied to .ui-datepicker-group (although the relevant class is applied via js) and hence they do not expand to the entire width of the container.

From jQuery UI v1.11.4 css at line numbers 333 thru 341:

.ui-datepicker-multi-2 .ui-datepicker-group {
    width: 50%;
}
.ui-datepicker-multi-3 .ui-datepicker-group {
    width: 33.3%;
}
.ui-datepicker-multi-4 .ui-datepicker-group {
    width: 25%;
}

You can see that classes for ...multi-5 and beyond are not defined.

What is the best way of eliminating this white space?

Recommended solution:

Simply add more classes as required in your custom CSS. This is the recommended way (also suggested in the response here: https://forum.jquery.com/topic/datepicket-problem-with-width-when-showing-multiple-months). And also the cleanest solution.

Just add the following lines to your custom CSS:

.ui-datepicker-multi-5 .ui-datepicker-group { width: 20%; }
.ui-datepicker-multi-6 .ui-datepicker-group { width: 16.666%; }
.ui-datepicker-multi-7 .ui-datepicker-group { width: 14.285%; }
.ui-datepicker-multi-8 .ui-datepicker-group { width: 12.5%; }
.ui-datepicker-multi-9 .ui-datepicker-group { width: 11.111%; }
.ui-datepicker-multi-10 .ui-datepicker-group { width: 10%; }
.ui-datepicker-multi-11 .ui-datepicker-group { width: 9.0909%; }
.ui-datepicker-multi-12 .ui-datepicker-group { width: 8.333%; }

This will take care of all possibilities up to 12 months across. Add more classes if required, as per your use-case.

For the sake of completeness, here is a demo:

Snippet:

$("#myCalendar").datepicker({ numberOfMonths: 5, showButtonPanel: false });
.ui-datepicker-multi-5 .ui-datepicker-group { width: 20%; }
.ui-datepicker-multi-6 .ui-datepicker-group { width: 16.666%; }
.ui-datepicker-multi-7 .ui-datepicker-group { width: 14.285%; }
.ui-datepicker-multi-8 .ui-datepicker-group { width: 12.5%; }
.ui-datepicker-multi-9 .ui-datepicker-group { width: 11.111%; }
.ui-datepicker-multi-10 .ui-datepicker-group { width: 10%; }
.ui-datepicker-multi-11 .ui-datepicker-group { width: 9.0909%; }
.ui-datepicker-multi-12 .ui-datepicker-group { width: 8.333%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div id="myCalendar"></div>

And a customary Fiddle: https://jsfiddle.net/abhitalks/u07kfLaa/1/


Note: Do not attempt to change or forcibly override the core jQuery-UI CSS (unless it is absolutely unavoidable). This is not a recommended best-practice. You may end up with unexpected problems, e.g. like this artefact (shown in red circle) visible in the screenshot below, when you force the components inline-block:

enter image description here

And then, you will end up adding more overrides fighting that and possibly get more problems. Try to keep it clean.

Community
  • 1
  • 1
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
5

It looks like a jQuery UI design oversight to me - I can't think of a reason why that extra whitespace would be intended. As you said, the widget has a fixed width in em, so this isn't just an issue of the default behavior of display: block.

In any case, we can eliminate that extra whitespace with the following steps:

  1. Set display: inline-block and width: auto on the datepicker widget so its width shrinks to fit its contents.

  2. To each individual calendar element, remove the float and use inline-block positioning instead (set float: none and display: inline-block).

  3. Set white-space: nowrap on the datepicker widget. This keeps all the months on one line, preventing them from wrapping onto a second line.

We will also need to use !important on a few of these rules to get them to override the rules from the default jQuery UI stylesheet.

Here is a screenshot of what the final result looks like:

Final Result Screenshot


Here is a Live Demo of the code in action:

$("#myCalendar").datepicker({
  numberOfMonths: 6,
  showButtonPanel: false
});
.ui-datepicker {
    display: inline-block !important;
    width: auto !important;
    white-space: nowrap;
}

.ui-datepicker-multi .ui-datepicker-group {
    float: none !important;
    display: inline-block;
}
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>

<div id="myCalendar"></div>

And a JSFiddle Version of the code: https://jsfiddle.net/cjpmyp1j/1/


As a side note, on the off-chance you were planning on setting inline styles because you are unable to include a stylesheet in your document head, look into using a scoped stylesheet in your document body alongside the jQuery UI element.

Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78