|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- ---
- title: Widget Styling Using Only CSS
- order: 65
- layout: page
- ---
-
- [[widget-styling-using-only-css]]
- = Widget styling using only CSS
-
- The preferred way of styling your widget is to only use static CSS
- included in the theme's styles.css file. For information on how to
- create custom themes, please refer to
- https://vaadin.com/book/-/page/themes.creating.html. Your component can
- be styled using the CSS class names that are defined to the widget using
- `setStyleName`.
-
- Normal styling of components works in the same way as any styling using
- CSS, but there are some special features to pay attention to when Vaadin
- 7 is used.
-
- [[some-sizing-theory]]
- Some sizing theory
- ~~~~~~~~~~~~~~~~~~
-
- All Vaadin 7 components get the CSS class v-widget which sets the
- box-sizing to border-box. This causes borders and paddings to be
- considered when the browser calculates the component's size. This means
- that e.g. a component with padding: 5px and width: 100% inside a 200px
- wide slot will fill the slot without any overflow because the inner
- width of the component will be calculated to 190px by the browser.
-
- The Vaadin 7 server side API allows setting the size of the component in
- three different ways:
-
- * Undefined size, set e.g. using `setWidth(null)`, means that the
- component's size should have it's default size that might vary depending
- on its content.
- * Relative size, set e.g. using `setWidth("100%")` means that the
- component's size is determined by the size and settings of the
- component's parent.
- * Fixed size, set e.g. using `setWidth("250px")` or `setWidth("10em")` means
- that the component's size is fixed, so that the parent doesn't affect
- the size and neither does the component's content.
-
- The three different ways of setting the size means that a component
- should both support having its own natural size and filling the
- allocated space depending on how the size is set. This usually means
- that the main area of the component should adjust based on the settings.
-
- [[a-simple-sample]]
- A simple sample
- ~~~~~~~~~~~~~~~
-
- Consider e.g. a simple date picker component with a text field where a
- date can be entered and where the currently selected is displayed and a
- button that is used to open a calendar view where a date can be picked
- using the mouse.
-
- [source,java]
- ....
- public class MyPickerWidget extends ComplexPanel {
- public static final String CLASSNAME = "mypicker";
-
- private final TextBox textBox = new TextBox();
- private final PushButton button = new PushButton("...");
-
- public MyPickerWidget() {
- setElement(Document.get().createDivElement());
- setStylePrimaryName(CLASSNAME);
-
- textBox.setStylePrimaryName(CLASSNAME + "-field");
- button.setStylePrimaryName(CLASSNAME + "-button");
-
- add(textBox, getElement());
- add(button, getElement());
-
- button.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- Window.alert("Calendar picker not yet supported!");
- }
- });
- }
- }
- ....
-
- We then add this basic styling to the theme CSS file
-
- [source,scss]
- ....
- .mypicker {
- white-space: nowrap;
- }
- .mypicker-button {
- display: inline-block;
- border: 1px solid black;
- padding: 3px;
- width: 15px;
- text-align: center;
- }
- ....
-
- `display: inline-block` makes the button continue on the same line as the
- text field, placing it to the right of the field. We also add
- `white-space: nowrap` to the main div element to ensure the button is not
- wrapped to the next row. Finally, there is some padding and a border to
- make the button look more like a real button.
-
- [[using-available-space]]
- Using available space
- ^^^^^^^^^^^^^^^^^^^^^
-
- This simple layout works well as long as the component's has it's
- default undefined width. Changing the width from the server does however
- not have any visible effect because only the size of the main div is
- changed. If the component is made smaller, the contents goes beyond the
- size of the element (this can be verified by adding `overflow: hidden;` to
- `.mypicker`) and if it gets larger the extra space is just left as empty
- space to the right of the button.
-
- The first step towards making the size adjust is to make the text field
- adjust to the main div element's width whenever the width is something
- else then than undefined. In these situations, Vaadin 7 adds a
- `v-has-width` class to the component's main element (`v-has-height` added
- when the height is not undefined).
-
- [source,scss]
- ....
- .mypicker.v-has-width > .mypicker-field {
- width: 100%;
- }
- ....
-
- With this additional CSS, the text field directly inside a picker that
- has a defined width gets full width.
-
- [[making-room-for-the-button-again]]
- Making room for the button again
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- We're however not done yet. Setting the width of the text field to 100%
- makes it as wide as the main div is, which means that the button goes
- outside the main div. This can be verified using the DOM inspector in
- your browser or by setting `overflow: hidden` to the style for `mypicker`.
- To reserve space for the button, we can add some padding to the right
- edge of the main div element. This does however cause the padding space
- to remain unused if the component size is undefined. To compensate for
- this, negative margin can be added to the right edge of the button,
- effectively reducing its occupied size to 0px.
-
- Finally, we need to use `box-sizing: border-box` to make the field's
- borders and paddings be included in the 100% width.
-
- The full CSS for the sample component:
-
- [source,scss]
- ....
- .mypicker {
- white-space: nowrap;
- padding-right: 23px;
- }
- .mypicker-button {
- display: inline-block;
- border: 1px solid black;
- padding: 3px;
- width: 15px;
- text-align: center;
- margin-right: -23px;
- }
- .mypicker.v-has-width > .mypicker-field {
- width: 100%;
- }
- .mypicker-field {
- -moz-box-sizing: border-box;
- -webkit-boz-sizing: border-box;
- box-sizing: border-box;
- }
- ....
|