updated on April 17, 2019
0. Introduction
It is important to give style to the components. Vaadin, sometimes is rejecting to assing some styles to the components, so it is important to test it.
1. Using CSS
We will put the CSS files in this folder:- Deployed Resources/webapp/frontend/css
2. The @HtmlImport annotation of the class
We will annotate the use of the "CSS file" in the LoginForm class with @HtmlImport(css/LoginForm.css).1 2 3 4 5 6 | @Route("") @PageTitle("Login") @HtmlImport("css/LoginForm.css") @SuppressWarnings("serial") public class LoginForm extends VerticalLayout implements II18nChange{ |
Here is the CSS code of LoginForm.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | !-- Remember to import custom-style, which is included in the Polymer package --> <link rel="import" href="../bower_components/polymer/lib/elements/custom-style.html"> <custom-style> <style> .edu-login{ /* height: 100%; margin: 0; padding: 0; */ max-width: 600px; max-height: 600px; color: var(--lumo-primary-text-color); /** Water image: Chrome needs url reltives from app while other url are relatives from css file */ background: linear-gradient(to bottom right, rgba(255,255,255,.3), rgba(255,255,255,.99)), url("../img/enterprise/enterprise02.jpeg"), /* GOOD in eclipse; BAD in chrome*/ url("frontend/img/enterprise/enterprise02.jpeg"); /* BAD in eclipse; GOOD in chrome*/ background-position: center; /* Center the image */ background-repeat: no-repeat; /* Do not repeat the image */ background-size: cover; /* Resize the background image to cover the entire container */ } .edu-login-header{ width: 100%; border-width:5px; border-bottom-style: solid; border-color: DodgerBlue; /*box-shadow: 10px 10px 5px LightGray;*/ /*box-shadow: 0px 1px 3px Blue;*/ } .edu-login-lang{ width: 100%; min-width: 300px; /*box-shadow: 10px 10px 5px gray;*/ } .edu-login-login{ /*background: LightYellow;*/ /*box-shadow: 5px 5px 3px LightGray;*/ } .edu-login-title{ /*background: yellow;*/ width: 100%; } .edu-login-buttons{ /*background: yellow;*/ /*color: var(--lumo-primary-text-color);*/ width: 100%; } /*****************************************/ /* MAIN VIEW */ /*****************************************/ .edu-main-header { width: 100%; background: yellow; margin: 0px; border: 0px; padding: 0px; } .edu-main-v1 { background: gray; margin: 0px; border: 0px; padding: 0px; } .edu-main-h11 { background: green; margin: 0px; border: 0px; padding: 0px; } .edu-main-h12 { background: beige; margin: 0px; } /*****************************************/ /* Stack login-screen vertically on narrow screen */ /* @media (max-width: 800px) { }*/ </style> </custom-style> |
3. Setting stile to components
There are some ways of setting styles to components, some methods are only allowed to certain component types:- component.setClassName("edu-login-header"). In this case, the style is in line 27.
- component.getStyle().set("font-size", "150%").set("text-align", "center"). It is used in a label. You can concatenate "sets".
- component.setWidth("15em"). In this casse it is applied to a combo.
4. Analyzing the Lofinform.css file
Here is a snippet of code showing an image in the background with transparency and gradient. Note that it did not work well on all browsers, so some alternatives have been used to offset this handicap.
1 2 3 4 5 6 7 | /** Water image: Chrome needs url reltives from app while other url are relatives from css file */ background: linear-gradient(to bottom right, rgba(255,255,255,.3), rgba(255,255,255,.99)), url("../img/enterprise/enterprise02.jpeg"), /* GOOD in eclipse; BAD in chrome*/ url("frontend/img/enterprise/enterprise02.jpeg"); /* BAD in eclipse; GOOD in chrome*/ background-position: center; /* Center the image */ background-repeat: no-repeat; /* Do not repeat the image */ background-size: cover; /* Resize the background image to cover the entire container */ |
The rest of the details include common tags as : margin, border....
5. The LoginForm class with style.
Here is the new code of the class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | package openadmin.ui; import javax.annotation.PostConstruct; import javax.inject.Inject; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Html; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.dependency.HtmlImport; import com.vaadin.flow.component.html.Image; import com.vaadin.flow.component.html.Label; import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.PasswordField; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import openadmin.session.SessionData; import openadmin.utils.VaadinUtils; @Route("") @PageTitle("Login") @HtmlImport("css/LoginForm.css") @SuppressWarnings("serial") public class LoginForm extends VerticalLayout implements II18nChange{ private TextField userName; private PasswordField password; private Button login; private LocaleCombo langCombo; private Label lblUserName; private Label lblPassword; private Label lTitle; private Image imageLang; @Inject private SessionData sesData; public LoginForm() { } /** * Initialization */ @PostConstruct private void init() { setClassName("edu-login"); add(getHeaderPanel()); add(getLangSelectorPanel()); add(getLoginPanel()); } /** Enterprise header **/ private HorizontalLayout getHeaderPanel() { HorizontalLayout headerPanel = new HorizontalLayout(); headerPanel.setClassName("edu-login-header"); Image logo = new Image("frontend/img/enterprise/enterprise05.jpeg", "logo"); headerPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, logo); headerPanel.add(logo); HorizontalLayout title = new HorizontalLayout(); title.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER); lTitle=new Label(getTranslation ("main.enterprise")); lTitle.getStyle() .set("font-size", "150%") .set("text-align", "center"); headerPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, lTitle); title.add(lTitle); title.setClassName("edu-login-title"); headerPanel.add(title); return headerPanel; } private HorizontalLayout getLangSelectorPanel() { HorizontalLayout langSelPanel = new HorizontalLayout(); langSelPanel.setClassName("edu-login-lang"); langSelPanel.setJustifyContentMode(FlexComponent.JustifyContentMode.END); // 1. Language ComboBox. langCombo = new LocaleCombo(sesData, this); langCombo.setWidth("15em"); langCombo.setClassName("edu-langcombo"); langCombo.getStyle().set("font-weight","bold"); langSelPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, langCombo); langSelPanel.add(langCombo); // 2.Flag Icon imageLang = new Image("frontend/icon/flags/" + sesData.getLangEnum().name() + ".png", "language"); //imageLang = new Image("frontend/icon/flags/" + lEnum.name() + ".png", "language"); // Jetty imageLang.getStyle().set("vertical-align", "middle").set("padding-left", "25"); langSelPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, imageLang); langSelPanel.add(imageLang); return langSelPanel; } private Component getLoginPanel() { VerticalLayout loginPanel= new VerticalLayout(); loginPanel.setClassName("edu-login-login"); VerticalLayout loginForm = new VerticalLayout(); loginForm.setWidth("300px"); // 1. User lblUserName = new Label(getTranslation ("login.user")); userName=new TextField(); userName.setValue("admin"); userName.setWidth("5em"); loginForm.add(lblUserName, userName); //2. Password lblPassword = new Label(getTranslation("login.password")); password = new PasswordField(); password.setWidth("15em"); loginForm.add(lblPassword, password); //3. Line separation loginForm.add(new Html("<br/>")); //4. Buttons layout HorizontalLayout buttonsLay = new HorizontalLayout(); buttonsLay.setClassName("edu-login-buttons"); buttonsLay.setJustifyContentMode(FlexComponent.JustifyContentMode.END); loginForm.add(buttonsLay); buttonsLay.add(login = new Button(getTranslation("login.login"), VaadinIcon.SIGN_IN.create())); //5. Login button login.addClickListener(event -> login()); //assign action to button login.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_PRIMARY); //6 Keyboard event listeners loginForm.getElement().addEventListener("keypress", event -> login()).setFilter("event.key == 'Enter'"); loginPanel.setHorizontalComponentAlignment(FlexComponent.Alignment.CENTER, loginForm); loginPanel.add(loginForm); return loginPanel; } /** * Try to log in if credentials are correct */ private void login() { if (userName.getValue().length()<1 || password.getValue().length()<1) { showNotification("login.invalid_credentials", 2000); userName.focus(); // usr & password credentials }else if (userName.getValue().equals("user") && password.getValue().equals("password")) { VaadinUtils.setSessionAttribute("CURRENT_USER", userName.getValue()); getUI().get().navigate("main"); }else { showNotification("login.invalid_credentials", 2000); userName.focus(); } } /** * Show notification * @param i18nKey * @param duration */ public void showNotification(String i18nKey, int duration) { String translatedMessage=this.getTranslation(i18nKey); Notification not=new Notification(translatedMessage); not.setDuration(duration); not.open(); } /** * Change labels according to Locale */ @Override public void changeI18nLabels() { lTitle.setText(getTranslation ("main.enterprise")); lblUserName.setText(getTranslation("login.user")); lblPassword.setText(getTranslation("login.password")); login.setText(getTranslation("login.login")); imageLang.setSrc("frontend/icon/flags/" + sesData.getLangEnum().name() + ".png"); //imageLang.setSrc("frontend/icon/flags/" + lEnum.name() + ".png"); //Jetty } } |
and here is the output.
Happy codding