Button positioning different on iOS then Windows and Android - css

I have a span what has 2 elements, input and svg.
I want the svg to be centered vertically in the input field.
I have 3 devices where I'm testing the design of my PWA.
Windows 10 - Google Chrome
Android 6.0 - Google Chrome
iOS 12.+ - Safari
On both Windows and Android it's centered vertically, only not on the iOS device.
Does anyone have an idea what this would fix?
React Component:
<StyledInputSpan>
<StyledInput />
<StyledClearButton />
</StyledInputSpan>
Styled Component:
export const StyledInput = styled.input`
//Reset box-shadow
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
display: block;
padding: 0.75em 2em 0.75em 0.75em; //Extra padding on the right for the clear button.
font-size: 1em;
//Hide the standard clear button.
&[type=search]::-webkit-search-cancel-button {
display: none;
}
`;
export const StyledClearButton = styled.button`
position: absolute;
top: calc(2.8em - env(safe-area-inset-top)); //env() is for the nodge on iOS.
right: 0;
`;
const StyledInputSpan = styled.span`
display: flex;
align-items: center;
`;

Find out that using env(safe-area-inset-top) is not what I was looking for.
env(safe-area-inset-top) works only for the top of your app on iOS.
When you use env(safe-area-inset-top) it push down your app with the height of the nodge.
I changed my css/styled component to:
export const StyledInput = styled.input`
//Reset box-shadow
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
display: block;
padding: 0.75em 2em 0.75em 0.75em; //Extra padding on the right for the clear button.
font-size: 1em;
//Hide the standard clear button.
&[type=search]::-webkit-search-cancel-button {
display: none;
}
`;
export const StyledClearButton = styled.button`
position: absolute;
top: 27.5%;
transform: translate(0, -50%);
right: 0;
`;
const StyledInputSpan = styled.span`
position: relative;
display: flex;
align-items: center;
`;

Related

Is there any way i can style an element based on other elements state using styled components?

I just started using styled-components and currently converting all my css into styled components in a project. But i am not sure how to achive some things and i could not find anything relevant in documentation too. I would like to know if the following problem is achievable using this approach in styled-components.
I have two checkboxes(radio input), if its checked i want to style a span element(Dot component in this case).
<div className="acc__type">
<RadioInput type="radio" name="accType" id="dot-1" required />
<RadioInput type="radio" name="accType" id="dot-2" required />
<Category>
<AccTypeLabel for="dot-1">
<Dot></Dot>
<AccTypeTitle>Student</AccTypeTitle>
</AccTypeLabel>
<AccTypeLabel for="dot-2">
<Dot></Dot>
<AccTypeTitle>Staff</AccTypeTitle>
</AccTypeLabel>
</Category>
</div>
here are my styled components
export const RadioInput = styled.input`
display: none;
`;
export const Category = styled.div`
display: flex;
width: 80%;
margin: 15px 0;
justify-content: space-between;
`;
export const AccTypeLabel = styled.label`
display: flex;
align-items: center;
`;
export const AccTypeTitle = styled.div`
font-size: 20px;
font-weight: 500;
`;
export const Dot = styled.span`
height: 18px;
width: 18px;
background: #d9d9d9;
border-radius: 50%;
margin: 10px;
border: 5px solid transparent;
transition: all 0.3s ease;
//here iam trying to change this components styles based on <RadioInput/> components state.
#dot-1:checked & {
border-color: #d9d9d9;
background: #9b59b6;
}
`;
in css i did this and it worked
#dot-1:checked ~ span,
#dot-2:checked ~ span {
border-color: var(--sub-grey);
background: var(--main-purple);
}
/* <Dot/> component was span here */
any help!
In Styled Components it's an ever so slightly different syntax, the reason is that it hashes the class names in a way that makes it difficult to target them. So this is how you do it in a way that ensures SC knows what's what:
const dot1StyledComponent = styled.div`
...
`;
${ dot1StyledComponent }:checked ~ span {
border-color: #d9d9d9;
background: #9b59b6;
}

Using mix-blend-mode on child of parent which has blur backdrop-filter makes blending black

Currently, I have a background image, and a navbar which has its background blurred using backdrop-filter. The navbar links, when not hovered, look like this:
Not hovered
This is working correctly, but on hover this is what it should look like (this is from figma):
Hovered
I was attempting to use mix-blend-mode to create this knockout effect, however it seems that when using a combination of both backdrop filter on a parent and mix-blend-mode on a child the blending does not work. Here's what it looks like: Navbar link
Removing the blur effect makes the effect work, but the blur is important.
Here's the code:
Navbar.module.scss
.nav {
font-family: 'Kumbh Sans', sans-serif;
display: flex;
backdrop-filter: blur(16px);
border: {
top: none;
left: none;
bottom: 3px solid $fg;
right: 3px solid $fg;
}
* {
display: flex;
align-items: center;
padding: {
top: 1rem;
bottom: 1rem;
}
}
}
.link {
backdrop-filter: none;
font-size: 18pt;
color: $fg;
display: block;
text-decoration: none;
padding: {
left: 1rem;
right: 1rem;
}
&:hover {
background-color: $fg;
color: black;
mix-blend-mode: screen;
}
}

Styled-Components mobile menu

I'm trying to achieve the following result. I have a responsive menu, however when the screen is less than 768px should hide a few elements (the ItemsMenu and LanguageItems) from the horizontal menu that it is for the desktop and display in the burger menu for mobile.
I'm having an issue because if I use display: none; it'll hide in both displays, for desktop and for mobile. How would be a better approach to achieve this result:
Component:
function Languages() {
const [language, setLanguage] = useState("en");
const handleLanguage = (language) => (event) => {
setLanguage(language);
};
return (
<>
<Lang>
<Logo>
<h1>Flávio</h1>
</Logo>
<ItemsMenu>
<li>{languages[language].about}</li>
<li>{languages[language].project}</li>
<li>{languages[language].contact}</li>
</ItemsMenu>
<LanguageIcon>
<img src={English} alt="EN" onClick={handleLanguage("en")} />
<img src={Japanese} alt="JP" onClick={handleLanguage("jp")} />
<img src={Russian} alt="RU" onClick={handleLanguage("ru")} />
<img src={Portuguese} alt="PT-BR" onClick={handleLanguage("ptbr")} />
</LanguageIcon>
</Lang>
</>
);
}
Styled-component:
import styled from "styled-components";
export const Lang = styled.div`
display: flex;
justify-content: space-between;
margin: auto;
width: 100%;
li:hover {
transition: all 0.2s ease-in-out;
transform: scale(1.5);
}
`;
export const Logo = styled.div`
color: #2e186a;
cursor: pointer;
`;
export const ItemsMenu = styled.ul`
display: flex;
justify-content: center;
cursor: pointer;
color: #2e186a;
margin: auto;
li {
display: inline-block;
color: #2e186a;
cursor: pointer;
padding-left: 1.5rem;
}
#media (max-width: 768px) {
/* display: none; */
}
`;
export const LanguageIcon = styled.div`
#media (max-width: 768px) {
/* display: none; */
}
img {
height: 2em;
margin-left: 1em;
cursor: pointer;
}
img:hover {
transition: all 0.2s ease-in-out;
transform: scale(1.5);
}
`;

React styled component animation not working

I am trying to create an animation for form textfield and label.
I want to be able to change the position of LabelText to top of the TextBox component.
Please let me know what I am missing on, My entered text and label are overlapping i.e. label is not animated.
Request help!
Styled components:
export const TextBox = styled.input`
display: flex;
width: 100%;
height: 2em;
border-radius: 5px;
border: none;
background: ${styles.backgroundGradient};
`;
export const LabelText = styled.label`
position: absolute;
top: 0;
left: 0;
font-size: 18px;
line-height: 16px;
pointer-events: none;
transition: 0.5s;
color: ${styles.formContentColor};
${TextBox}:focus ~ &,
${TextBox}:not([value=""]) ~ & {
top: -1.5em;
left: 0;
color: ${styles.formContentColor};
font-size: 20px;
}
`;
export const InputWrapper = styled.div`
position: relative;
width: 60%;
`;
Order of placement in components
<InputWrapper>
<LabelText>Product Name</LabelText>
<TextBox type="text" />
</InputWrapper>
I read through comment by #mosh feu and other answers on stackoverflow.
Detect if an input has text in it using CSS -- on a page I am visiting and do not control?
There are couple of approaches that can serve the purpose i.e. to check whether input field is empty or not drafting them below for future refrrence.
input:not(:placeholder-shown):
input:not([value=""]):
In my case input is value of TextBox.
export const LabelText = styled.label`
position: absolute;
top: 1.5em;
left: 0;
font-size: 18px;
line-height: 16px;
pointer-events: none;
transition: 0.6s;
color: ${styles.formContentColor};
${TextBox}:focus ~ &,
${TextBox}:not(:placeholder-shown) ~ & {
top: 0;
left: 0;
color: ${styles.formContentColor};
font-size: 16px;
}
`;

override css for html5 form validation/required popup

How can I override the default popup for a required field on a HTML5 form?
Example: http://jsfiddle.net/uKZGp/ (make sure you click the submit button to see the popup)
The HTML
<form>
<input type="text" name="name" id="name" placeholder="Name*" required="required" />
<input type="submit" />
</form>
NOTE: You must view this with a HTML5 browser like Google Chrome or FireFox.
This link doesn't solve my question but it might make someone think outside of the box:
http://www.the-art-of-web.com/html/html5-form-validation/
http://adhockery.blogspot.com/2011/03/styling-with-html5-form-validation.html
It's impossible to change the validation style with only HTML5/CSS3.
It's part of the browser. The only attribute I figured out to change is the error message by using this example:
document.getElementById("name").setCustomValidity("Lorum Ipsum");
But, as shown in this example : http://jsfiddle.net/trixta/qTV3g/, you can override the panel style by using jQuery. This is not a plugin, it's a core functionality, uses a DOM lib called Webshims and, of course, some CSS to style the popups.
I found that very useful example in this bug post titled Improve form validation error panel UI.
I think this is the best solution you can find and only way to override the basic (ugly) error panel.
Regards.
I'm not sure why, but ::-webkit-validation-bubble-message { display: none; } wouldn't work for me.
I was able to get the desired result (tested in FF 19, Chrome Version 29.0.1547.76 m) by preventing the default behavior of the invalid event, which does not bubble.
document.addEventListener('invalid', (function(){
return function(e){
//prevent the browser from showing default error bubble/ hint
e.preventDefault();
// optionally fire off some custom validation handler
// myvalidationfunction();
};
})(), true);
Hope that helps others - I looked everywhere for this.
For webkit, you can use ::-webkit-validation-bubble-message. For example to hide it:
::-webkit-validation-bubble-message { display: none; }
There are also:
::-webkit-validation-bubble-arrow-clipper{}
::-webkit-validation-bubble-arrow{}
::-webkit-validation-bubble{}
::-webkit-validation-bubble-top-outer-arrow{}
::-webkit-validation-bubble-top-inner-arrow{}
::-webkit-validation-bubble-message{}
Update: Chrome does not allow styling form validation bubbles anymore: https://code.google.com/p/chromium/issues/detail?id=259050
For firefox you can experiment with :-moz-placeholder {}.
The current default email validation is currently one of the ugliest things I have ever seen Google design!
However it seems to be contained in a standard div so you can make some changes to it, if you remember to then reset these values.
I've found you can alter the background, font size and colour, border and shadow, like so
div {
background: rgba(0,0,0,0.8);
color: #333;
font-size: 11px;
border: 0;
box-shadow: none;
}
If you then overwrite these for divs inside the html tag, then only the validation is ultimately affected.
html div {
background: rgba(0,0,0,1);
color: #000;
font-size: 12px;
}
Unfortunately some of the key attributes that you'd want to change, such as margin and font-weight, cannot be altered.
NB. This technique currently only works for Chrome (12), i.e. not work for Firefox 4, Opera 11 or Safari (Win 7).
Appended a class to the input type. and displayed message there .Hope that helps after little customization. working codepen:
document.querySelector('#frm').addEventListener('submit', e => {
e.preventDefault();
e.currentTarget.classList.add('submitted');
});
body {
font-family: Helvetica, sans-serif;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
overflow: hidden;
width: 100%;
height: 100vh;
background: #ffa500;
}
form > div {
position: relative;
margin-bottom: 10px;
}
.theTooltip {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
will-change: opacity, visibility;
max-width: 250px;
border-radius: 5px;
background-color: rgba(0,0,0,0.7);
padding: 15px;
color: #fff;
box-sizing: border-box;
display: inline-block;
position: absolute;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translate(15%, -50%);
transform: translate(15%, -50%);
top: 50%;
left: auto;
right: auto;
bottom: auto;
visibility: hidden;
margin: 0;
opacity: 0;
-webkit-transition: opacity 0.3s ease-out;
transition: opacity 0.3s ease-out;
z-index: 100;
}
.theTooltip:after {
content: '';
position: absolute;
width: 0;
height: 0;
top: 50%;
margin-top: -10px;
left: -10px;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid rgba(0,0,0,0.7);
}
label {
display: inline-block;
vertical-align: center;
}
input {
background: #fff;
border: 1px solid transparent;
cursor: pointer;
display: inline-block;
overflow: visible;
margin: 0;
outline: 0;
vertical-align: center;
text-decoration: none;
width: auto;
border-radius: 3px;
cursor: text;
padding: 7px;
}
input:focus,
input:active {
outline: none;
}
.submitted input:invalid {
border: 1px solid #f00;
}
.submitted input:invalid ~ .theTooltip {
visibility: visible;
opacity: 1;
}
.submitted input:valid ~ .theTooltip {
-webkit-transition: opacity 0.3s, visibility 0s 0.3s;
transition: opacity 0.3s, visibility 0s 0.3s;
}
<form id="frm" action="action">
<div>
<label>Email</label>
<input type="email" required="required"/><span class="theTooltip">Invalid email</span>
</div>
<div>
<button formnovalidate="formnovalidate">OK</button>
</div>
</form>
I understand that this is a rather old question but I have found this library that I think this may be beneficial to other that find this.
http://afarkas.github.io/webshim/demos/index.html

Resources