Can't override checkbox style using crispy forms - css

While creating forms for my app I had to make a custom checkbox (I am terrible with css so this was not easy). I got it to work and it looks like this when I create the form manually:
The manual html is
<div class="checkbox icheck-primary">
{{ form.active }}
<label for="id_active">Active</label>
</div>
But when using the wrapper_class attribute on a crispy forms Field it displays as standard:
And the crispy forms code:
self.helper.layout = Layout(
Fieldset(
'Add Contact',
'first_name',
Field('active', wrapper_class='icheck-primary', css_class='icheck-primary')
))
I tried using a custom Div template but I couldn't get it to work. In the docs all I could find was the wrapper_class.
Am I missing something simple or could someone point me in the right direction?
[Edit]
HTML output from crispy_forms:
<div id="div_id_active" class="checkbox icheck-primary">
<label for="id_active" class="">
<input name="active" class="checkboxinput" id="id_active" checked="" type="checkbox">
Active
</label>
</div>
And here is my manual/forms generated html
<div class="checkbox icheck-primary">
<input name="stay_logged_in" class="checkbox icheck-primary" id="id_stay_logged_in" type="checkbox">
<label for="id_stay_logged_in">Remember me</label>
</div>
[Edit 2] This is a sample of the css selectors
.radio > input[type="radio"]:first-child:checked + label::before,
.checkbox > input[type="checkbox"]:first-child:checked + label::before,
.radio > input[type="radio"]:first-child:checked + input[type="hidden"] + label::before,
.checkbox > input[type="checkbox"]:first-child:checked + input[type="hidden"] + label::before {
content: "\e013";
display: inline-block;
font-family: 'Glyphicons Halflings';
font-weight: normal;
font-size: 10px;
color: #b4aba1;
position: absolute;
width: 22px;
height: 22px;
line-height: 20px;
border: 2px solid #b4aba1;
border-radius: 0 !important;
background-color: #0060a1 !important;
text-align: center;
margin-left: -29px;
vertical-align: text-top;
}

After some help in the comments from #dirn I went back and made a custom template.
Since all of my checkboxes should look this same I created a checkboxinput_template based on the existing crispy_forms templates:
{% load crispy_forms_field %}
<div id="div_{{ field.auto_id }}" class="checkbox icheck-primary {% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
{{ field }}
<label class="control-label {{ label_class }}" for="id_{{ field.html_name }}">{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}</label>
<div class="controls {{ field_class }}">
{% include 'bootstrap3/layout/help_text.html' %}
</div>
</div>
I added the icheck-primary class to the surrounding div and moved the field itself out of the label tag. This allowed the selectors to work properly.
I think this could also be done by overriding the fields.html but for the moment this solves my problem.
This is probably not the best solution and I'd appreciate it if anyone could share a better one.

I have no experience with django-crispy-forms, but use django-widget-tweaks for adding css to django forms. You only need to adjust templates, no python code. Makes it a lot easier and you keep styling separate from code.

Related

How to update css styles in Shopify ajax cart

I'm building ajax cart for my client's Shopify store with liquid-ajax-cart. Now I'm trying to add a progress bar that shows how far a user from the free shipping option. The bar is the .free-shipping-bar element within the .minicart__header.
The free shipping starts from $100 (free_shipping_threshold_price liquid variable) so I want the bar to be filled completely if the cart total is $100 or more.
If the cart total is less than $100 then I want to fill the bar accordingly (40% for $40, 50% for $50 etc.).
The HTML of the section updates as it should when a user clicks "add to cart" but the css ({% style %}) doesn't.
Is possible to fix it somehow so that css code updates by ajax also?
<div class="minicart-wrapper">
<div class="minicart-overlay" data-ajax-cart-toggle-class-button="js-ajax-cart-open"></div>
<div class="minicart" data-ajax-cart-section>
<div class="minicart__header">
<h3 class="title">{{ 'general.cart.title' | t }}</h3>
<div class="free-shipping-bar"></div>
<button class="close-button" data-ajax-cart-toggle-class-button="js-ajax-cart-open" type="button"></button>
</div>
<div class="minicart__items">
<!-- items code -->
</div>
<div class="minicart__footer">
<!-- footer code -->
</div>
</div>
</div>
{%- liquid
assign free_shipping_threshold_price = 10000
assign free_shipping_percent = cart.total_price | times: 100 | divided_by: free_shipping_threshold_price
-%}
{% style %}
.free-shipping-bar {
position: relative;
width: 100%;
height: 3px;
background-color: #c4c4c4;
}
.free-shipping-bar:after {
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: {{ free_shipping_percent }}%;
background-color: #005030;
max-width: 100%;
}
{% endstyle %}
{% schema %}
{
"name": "Ajax Cart",
"settings": [
]
}
{% endschema %}
according to the docs only the part that is inside the data-ajax-cart-section element will get updated. So you need to put the CSS styles that should be updated within the element:
{%- liquid
assign free_shipping_threshold_price = 10000
assign free_shipping_percent = cart.total_price | times: 100 | divided_by: free_shipping_threshold_price
-%}
<div class="minicart-wrapper">
<div class="minicart-overlay" data-ajax-cart-toggle-class-button="js-ajax-cart-open"></div>
<div class="minicart" data-ajax-cart-section>
<style>
.free-shipping-bar:after {
width: {{ free_shipping_percent }}% !important;
}
</style>
<!-- Mini-cart code -->
</div>
</div>

Angular component with custom validation

I have an Angular 5 component that is basically just a label and input
<div class="form-group">
<label for="wwid">WWID</label>
<input id="wwid" required ...lots of attrs...>
</div>
Using CSS I've then defined a style:
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
When the field is blank, I'm getting two red borders. The one on the input field that I want, but also one to the right of the label that I do not want. How do I get rid of the red line on the label?
Here's the actual full HTML that used by the component.
<ng-template #listSelectionFormatter let-r="result">
<span>{{r.wwid}} - {{r.fullName}}</span>
</ng-template>
<div class="form-group">
<label *ngIf="labelText" for="wwid">
{{ labelText }}
<span *ngIf="isRequired"> <sup class="requiredIndicator">*</sup></span>
</label>
<!-- inputFormatter is the format for what is placed into the input field after choosing from the dropdown -->
<input id="wwid" type="text"
class="form-control"
placeholder="Search by WWID, IDSID, Name or Email"
(selectItem)="onWorkerSelected($event.item)"
(input)="onTextFieldChanged($event.target.value)"
[ngModel]="selectedWorker"
[ngbTypeahead]="search"
[inputFormatter]="selectedResultsFormatter"
[resultTemplate]="listSelectionFormatter"
[disabled]="disabled"
[required]="required"
/>
<span *ngIf="searching">searching…</span>
<div class="invalid-feedback" *ngIf="searchFailed">Lookup failed.</div>
</div>
The requiredIndicator thing is just for an older style I was using to show an asterisk if it was required, and used this CSS:
.requiredIndicator {
color: red;
font-size: larger;
vertical-align: baseline;
position: relative;
top: -0.1em;
}

How to add a hover effect on a dropdown?

I'm currently designing a new website and I added a dropdown which works perfectly fine when clicked. I basically want it to show that dropdown when hovered.
What I tried was:
{% include 'currency-picker' %}
<style>
.currency-picker {
background-color: transparent;
font-size: 12pt;
font:Montserrat;
letter-spacing: 2px;
color: black;
}
.currency-picker:hover {
display: block;
}
.currency-picker:hover {
background-color: white;
This is the dropdown itself:
<label class="currency-picker__wrapper">
<span class="currency-picker__label"></span>
<select class="currency-picker" name="currencies" style="display: inline; width: auto; vertical-align: inherit;">
{% assign codes = 'USD,EUR,GBP,CAD,ARS,AUD,BBD,BDT,BSD,BHD,BRL,BOB,BND,BGN,ILS,MMK,KYD,CLP,CNY,COP,CRC,HRK,CZK,DKK,DOP,XCD,EGP,XPF,FJD,GHS,GTQ,GYD,GEL,HKD,HUF,ISK,INR,IDR,NIS,JMD,JPY,JOD,KZT,KES,KWD,LVL,LTL,MXN,MYR,MUR,MDL,MAD,MNT,MZN,ANG,NZD,NGN,NOK,OMR,PKR,PYG,PEN,PHP,PLN,QAR,RON,RUB,SAR,RSD,SCR,SGD,SYP,ZAR,KRW,LKR,SEK,CHF,TWD,THB,TZS,TTD,TRY,UAH,AED,UYU,VEB,VND,ZMK' | split: ',' %}
{% assign supported_codes = settings.supported_currencies | split: ' ' %}
<option value="{{ shop.currency }}" selected="selected">{{ shop.currency }}</option>
{% for code in supported_codes %}
{% if code != shop.currency and codes contains code %}
<option value="{{ code }}">{{ code }}</option>
{% endif %}
{% endfor %}
</select>
</label>
The strange thing is, that the .currency-picker:hover {
background-color: white; works and it does indeed show the white background when hovered.
Is there anyone knowing a solutions of my problem?
Have a nice day and best regards,
Ismael
After looking at your code, is there any reason why you don't just use the same markup as the other dropdowns? Consistency is always key.
What you are trying to do does not work or is not allowed in the browser. Instead of using an actual "select" box, I would use the actual markup they are using on the other dropdowns which give you the exact functionality that you are looking for.
This code (taken from your site) should give you a clue on how to handle this. Also You ave an extra starting script tag on your page where you dropped that new test code..
Please note I changed the below code a bit to give you better reference. If you were to drop this code into your site, it would work, but you need to refactor it to make it dynamic.
<li class="site-nav__item site-nav__expanded-item site-nav--has-dropdown" aria-haspopup="true">
USD <span class="icon icon-arrow-down" aria-hidden="true"></span>
<ul class="site-nav__dropdown text-left">
<li>
EUR
</li>
<li>
CHF
</li>
</ul>
After my change...

Background for radio button for Django form

I found some peaces of code solving the issue, but all of those are using input tag and label tag which placed near each other. Django forms placed input inside label, that's why the code is ineffective in my case.
One of variant I tried here
Any advices or thoughts.
Thanks all!
input[type=radio] {
display:none;
}
input[type=radio] + label
{
background: #999;
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}
input[type=radio]:checked + label
{
background: #0080FF;
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}
Solved the issue customized form template and applied the solution on css above.
{% for field in form %}
{% for item in field %}
<input id="id_name_{{ forloop.counter0 }}" name="name" type="radio" value="{{ item.choice_value }}">
<label for="id_name_{{ forloop.counter0 }}">{{ item.choice_label }}</label>
{% endfor %}
{% endfor %}
I haven't check if my solution is right yet.
but you can write like this:
{% for field in form %}
{% for radio in field %}
{{ radio tag }}
<label for="{{ radio.id_for_label }}" title="{{ radio.choice_label }}"></label>
{% endfor %}
{% endfor %}
For more information,
you can read the official doc.

Horizontal organization using CSS/HTML5

Above is what I am trying to create as a login form (although there should be a mirror of 'login' after the right brace that says 'signup'). I'm having trouble getting the objects to line up horizontally as I wish. The second image (below) shows what I have. Yikes.
I obviously don't want the fieldset around it, but I our it there to try and group the username and password fields. Here is my code thus far. The HTML:
<head>
<meta content="en-us" http-equiv="Content-Language" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Login</title>
<script type="text/javascript" src="{{ STATIC_URL }}jquery1-6.4.min.js"></script>
<link rel="stylesheet" href="{{ STATIC_URL }}login.css" type="text/css"/>
</head>
<script>
function login(){
if($('username').text === '') alert('Please enter your username');
else if($('password') === '') alert('Please enter your password');
$('loginForm').submit();
}
</script>
<body>
<img src="{{ STATIC_URL}}logo.png" class='center'>
<br/>
<span class='login_signup_button'>
<a title='click to login' onClick='login()'>
login
</a>
</span>
<form method = 'POST' action='login' id='loginForm'>
<fieldset>
<label for="username">username</label>
<input type="text" id="username" face="helvetica"/>
</br>
<label for="password">password</label>
<input type="password" id="password" face="AmericanTypewriter"/>
</fieldset>
</form>
<span class='login_signup_button' value='submit'>
<a title='signup for omnicloud' href='signup' class='login_signup_button'>
signup
</a>
</span>
</body>
and the CSS (which is imported into the HTML):
#font-face{
font-family:AmericanTypewriter;
src:url('AmericanTypewriter.TTF');
}
body{
background-color:rgb(48,94,255);
}
image.center{
/*display: block; */
margin-left: auto;
margin-right: auto;
width:500px;
}
/* Used for braces */
h1{
font-family:AmericanTypewriter;
font-size:234pt;
color:rgb(249,255,41);
}
/* Used for login, signup, username, password */
p{
font-family:AmericanTypewriter;
font-size:42pt
color:rgb(255,255,255);
}
fieldset{
border: 10px solid rgb(255,255,255);
width: 500px;
margin: auto;
}
a{
background-color:rgb(48,94,255);
font-family:AmericanTypewriter;
font-size:42pt
color:rgb(255,255,255);
}
.login_signup_button button{
background-color:rgb(48,94,255);
font-family:AmericanTypewriter;
font-size:42pt
color:rgb(255,255,255)
border-bottom:0;
border-right:0;
border-top:0;
border-left:0;
display:block;
}
.login_signup_button a:hover{
background-color:rgb(249,255,41);
color:rgb(48,94,255);
}
EDIT: updated code to fix the action of login, added js function, formatted labels for s
Something like this. (Just a rough start).
Note that I'm using an image for the brackets (not seen here). I don't know which version of American Typewriter you're using, but I doubt it will look that thin at that size, and it's probably not worth loading an entire weight of a typeface just for those two characters. Sometimes an image is just better, even though it might not seem as elegant.
Note that I'm a common image replacement technique for the logo. This is better for SEO that simply using an <img> with alt text. (Which you should always include if you choose that route instead.)
Edit: And if you do want to use the font for the brackets, you might try using CSS :before and :after pseudo-classes to add the content around the fieldset or whatever you use as your container for those form elements.
It appears you want to maintain grouping of fields which fieldset provides but not happy with the lines around those fields. If that is the case then you can mark filedset border as none.
fieldset {
border: none;
}
I believe what you are trying to do is to have the input field show next to your text label.
This is how i would write the HTML:
<body>
<img src="logo.png" class="center"/>
<div id="signin">
<form action="path-to-submit" method="post">
<label for="username-field">Username</label>
<input id="username-field" type="text" name="username"/><br/>
<label for="password-field">Password</label>
<input id="password-field" type="password" name="password"/><br/>
<input type="submit" value="Login"/>
Signup for Omnicloud
</form>
</div>
</body>
Because and are inline elements, they will show up next to each-other. Using the br tag will create a line-break for the next set of fields.

Resources