summaryrefslogtreecommitdiffstats
path: root/documentation
diff options
context:
space:
mode:
authorErik Lumme <erik@vaadin.com>2017-09-13 11:27:27 +0300
committerErik Lumme <erik@vaadin.com>2017-09-13 11:27:27 +0300
commit2ca94c8f0525b2a96a52988278ce8050f1a9cbbd (patch)
tree67403159155d07dcea29b2ea2528f468a957736a /documentation
parent421020899176326406c7f501e5b54cd20257b86c (diff)
downloadvaadin-framework-2ca94c8f0525b2a96a52988278ce8050f1a9cbbd.tar.gz
vaadin-framework-2ca94c8f0525b2a96a52988278ce8050f1a9cbbd.zip
Migrate WidgetStylingUsingOnlyCSS
Diffstat (limited to 'documentation')
-rw-r--r--documentation/articles/WidgetStylingUsingOnlyCSS.asciidoc172
-rw-r--r--documentation/articles/contents.asciidoc1
2 files changed, 173 insertions, 0 deletions
diff --git a/documentation/articles/WidgetStylingUsingOnlyCSS.asciidoc b/documentation/articles/WidgetStylingUsingOnlyCSS.asciidoc
new file mode 100644
index 0000000000..609c8a566b
--- /dev/null
+++ b/documentation/articles/WidgetStylingUsingOnlyCSS.asciidoc
@@ -0,0 +1,172 @@
+[[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;
+}
+....
diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc
index 805407fcf7..5c4d262110 100644
--- a/documentation/articles/contents.asciidoc
+++ b/documentation/articles/contents.asciidoc
@@ -71,5 +71,6 @@ are great, too.
- link:PackagingSCSSOrCSSinAnAddon.asciidoc[Packaging SCSS or CSS in an add-on]
- link:RightAlignComparableNumericalFields.asciidoc[Right-align comparable numerical fields]
- link:CustomizingComponentThemeWithSass.asciidoc[Customizing component theme with Sass]
+- link:WidgetStylingUsingOnlyCSS.asciidoc[Widget styling using only CSS]
- link:CreatingAUIExtension.asciidoc[Creating a UI extension]
- link:CreatingAThemeUsingSass.asciidoc[Creating a theme using Sass]