CSS - Showing an error beneath an input - css

I am looking to show an error message below a text input like so
The message should not extend any wider than the width of the input, so I was thinking could I inherit the width of the input on say a span that sits below it?
Something like:
<div class="my-form-control-group has-error">
<input type="text" class="my-form-control" >
<p style="width:inherit;">Some Error Here</p>
</div>
My current attempt - http://jsfiddle.net/4eu2qkra/
I know this sample above will not work, and usage of inherit is wrong here since it will be looking to use the width of the parent div.
Is there a pure css way to inherit from a sibling element immediately before a target element? Maybe I'm going about this all the wrong way?!

Use your wrapper DIV to control the width of the input and the error message. Make sure that the input has width: 100%; so that it will fill the wrapper DIV.
<div class="control-wrap">
<input type="text">
<p>Error Message. Error Message</p>
</div>
* {
box-sizing: border-box;
}
.control-wrap {
width: 50%;
padding: 5px;
background-color: red;
border: 1px solid #666;
}
input {
width: 100%;
border: 1px solid #666;
}
p {
margin: 5px 0;
}
jsFiddle: http://jsfiddle.net/2krc8tyL/

You can wrap the input and error message in a div with display: table set on it, which will match the width of the largest child. This way it will adjust to the input's width.
.my-form-control-group {
display: table;
padding: 4px;
}
.my-form-control {
width: 250px;
border-width: 1px;
}
.my-form-control-group.has-error {
color:white;
border-color:red;
background-color: red;
padding: 1px 1px 4px 1px;
}
<div class="my-form-control-group has-error">
<input type="text" class="my-form-control" >
<div>Some Error Here</div>
</div>

The most obvious option is to use absolute positioning.
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.my-form-control-group {
display: inline-block;
position: relative;
background: red;
padding: 4px;
}
.my-form-control {
border-width: 1px;
display: block;
}
.error {
position: absolute;
left: 0;
top: 100%;
width: 100%;
background: red;
color: white;
padding: 4px;
}
<div class="my-form-control-group has-error">
<input type="text" class="my-form-control" />
<p class="error">Some Error Here Lorem ipsum dolor.</p>
</div>

Related

Is there a way to create a header that overlaps on the top of the border of a box using CSS? [duplicate]

I'd like to have a div that looks like this:
Is this possible to do with HTML + CSS? I will also be animating this div with jQuery. When the div is hidden I would like the title and the top line to show.
Yes, but it's not a div, it's a fieldset
fieldset {
border: 1px solid #000;
}
<fieldset>
<legend>AAA</legend>
</fieldset>
You can do something like this, where you set a negative margin on the h1 (or whatever header you are using)
div{
height:100px;
width:100px;
border:2px solid black;
}
h1{
width:30px;
margin-top:-10px;
margin-left:5px;
background:white;
}
Note: you need to set a background as well as a width on the h1
Example: http://jsfiddle.net/ZgEMM/
EDIT
To make it work with hiding the div, you could use some jQuery like this
$('a').click(function(){
var a = $('h1').detach();
$('div').hide();
$(a).prependTo('body');
});
(You will need to modify...)
Example #2: http://jsfiddle.net/ZgEMM/4/
I know a bit late to the party, however I feel the answers could do with some more investigation/input.
I have managed to create the situation without using the fieldset tag - that is wrong anyway as if I'm not in a form then that isn't really what I should be doing.
/* Styles go here */
#info-block section {
border: 2px solid black;
}
.file-marker > div {
padding: 0 3px;
height: 100px;
margin-top: -0.8em;
}
.box-title {
background: white none repeat scroll 0 0;
display: inline-block;
padding: 0 2px;
margin-left: 8em;
}
<aside id="info-block">
<section class="file-marker">
<div>
<div class="box-title">
Audit Trail
</div>
<div class="box-contents">
<div id="audit-trail">
</div>
</div>
</div>
</section>
</aside>
This can be viewed in this plunk:
Outline box with title
What this achieves is the following:
no use of fieldsets.
minimal use of CSS to create effect with just some paddings.
Use of "em" margin top to create font relative title.
use of display inline-block to achieve natural width around the text.
Anyway I hope that helps future stylers, you never know.
Text in Border with transparent text background
.box{
background-image: url("https://i.stack.imgur.com/N39wV.jpg");
width: 350px;
padding: 10px;
}
/*begin first box*/
.first{
width: 300px;
height: 100px;
margin: 10px;
border-width: 0 2px 0 2px;
border-color: #333;
border-style: solid;
position: relative;
}
.first span {
position: absolute;
display: flex;
right: 0;
left: 0;
align-items: center;
}
.first .foo{
top: -8px;
}
.first .bar{
bottom: -8.5px;
}
.first span:before{
margin-right: 15px;
}
.first span:after {
margin-left: 15px;
}
.first span:before , .first span:after {
content: ' ';
height: 2px;
background: #333;
display: block;
width: 50%;
}
/*begin second box*/
.second{
width: 300px;
height: 100px;
margin: 10px;
border-width: 2px 0 2px 0;
border-color: #333;
border-style: solid;
position: relative;
}
.second span {
position: absolute;
top: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.second .foo{
left: -15px;
}
.second .bar{
right: -15.5px;
}
.second span:before{
margin-bottom: 15px;
}
.second span:after {
margin-top: 15px;
}
.second span:before , .second span:after {
content: ' ';
width: 2px;
background: #333;
display: block;
height: 50%;
}
<div class="box">
<div class="first">
<span class="foo">FOO</span>
<span class="bar">BAR</span>
</div>
<br>
<div class="second">
<span class="foo">FOO</span>
<span class="bar">BAR</span>
</div>
</div>
<fieldset>
<legend> YOUR TITLE </legend>
<p>
Lorem ipsum dolor sit amet, est et illum reformidans, at lorem propriae mei. Qui legere commodo mediocritatem no. Diam consetetur.
</p>
</fieldset>
You can use a fieldset tag.
<!DOCTYPE html>
<html>
<body>
<form>
<fieldset>
<legend>Personalia:</legend>
Name: <input type="text"><br>
Email: <input type="text"><br>
Date of birth: <input type="text">
</fieldset>
</form>
</body>
</html>
Check this link: HTML Tag
For a duplicate, here another option with transform, no fieldset ( and rounded border required in the duplicates) :
Question
Help. I am not great at UX. I am creating an app in React and using Material UI for the look. I really want to create something like this
Where the "Some Title" is a dynamic field from my database as well as the contents. The thing I cannot figure out is what is the best (non skanky) way to add the title into the outline? Thoughts?
Answer position or transform can help you too :
* {
margin: 0;
padding:0;
box-sizing:border-box;
}
.fieldset {
border: solid;
color: #353fff;
border-radius: 1em;
margin: 2em 1em 1em;
padding:0 1em 1em;
}
.legend {
transform: translatey(-50%);
width: max-content;
background: white;
padding: 0 0.15em;
}
.fieldset li {
list-style-type: " - ";
}
<div class="fieldset">
<h1 class="legend">Some Title</h1>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>
If you are not in a position to add a field set, you can add a background to the element. In my situation, I had different colors in the input element and outside the input element, and also we have a hover color for the input element. So this is a fix I added linear-gradient background with outside color in the top half and transparent color in the bottom half.
I added the transparent color to the bottom half inorder to see the hover color when hovered.
.class-name {
background: linear-gradient(to bottom, #2a2b2d 50%, transparent 50%);
}
From a practical perspective, I think PeterS has the best answer. It's also presented in a very clear, didactical style.
Just to save others a few minutes converting it into more production-style code, I've done the following. Basically, it's what you would think you need: One div box inside another, with the outer div box providing the border, the inner providing the title contents with a negative margin shifting it up. A third div then contains the actual content.
This is the CSS:
.outer-border-box {
border: 2px solid black; border-top:3px solid black;}
.label-source-box {
padding: 0 3px; height: 100px; margin-top: -0.8em; }
.box-title {
background: white none repeat scroll 0 0;
padding: 0 2px;
margin-left: 4em;
font-weight:700; font-size:18px;
font-family: 'Avenir Next',Helvetica, sans-serif; }
This is the html:
<div class="outer-border-box">
<div class="label-source-box">
<span class="box-title">Promotional </span>
<div class="box-contents">
<h2>this is the contents</h2>
</div> </div> </div>
It is possible by using the legend tag.
Refer to http://www.w3schools.com/html5/tag_legend.asp

display table taking extra space on margin top

I tried to create one component that similar to input-group in bootstrap. The reason i was not using the default input-group class of bootstrap is in default I cannot add multiple buttons and input element in input group addon. so i decided to create custom input-group using display-table property but when I use this property some extra space added to top in buttons section.
I need to align the input and counter component in same line.
HTML Part
<div class="product-order-form" matAutocompleteOrigin #origin="matAutocompleteOrigin">
<div class="product-inputGroup tableElem">
<div class="tableRow">
<input class="form-control tableCell" type="text" matInput [formControl]="myControl" [matAutocomplete]="auto" [matAutocompleteConnectedTo]="origin">
<div class="counter tableCell">
<div class="counterContainer">
<div class="value-button" id="decrease" value="Decrease Value">-</div>
<input type="text" id="number" value="0" />
<div class="value-button" id="increase" value="Increase Value">+</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.tableElem{
display:table;
width:100%;
}
.tableRow{
display:table-row;
width:100%;
}
.tableCell{
display:table-cell;
}
.product-order-form{
height: 30px;
}
.counterContainer {
width: 150px;
height:30px;
}
.value-button{
text-align: center;
height: 100%;
width: 50px;
background: lightgray;
padding: 5px;
box-sizing: border-box;
float: left;
}
.value-button:hover {
cursor: pointer;
}
input#number{
text-align: center;
height: 100%;
border: none;
width: 50px;
float: left;
box-sizing: border-box;
border-top: 0.5px solid lightgray;
border-bottom: 0.5px solid lightgray;
}
here is my stackblitz
There are two issues here:
.product-order-form sets a height of 30px which means it is shorter than some of it's children / siblings. That would cause issues (try adding overflow:hidden to see it in action)
.tableCell has no vertical-align which would mean it will position itself at the top o/t component. Try adding vertical-align: middle and it should work fine
TL;DR
.tableCell[_ngcontent-c2] {
display: table-cell;
vertical-align: middle;
}
.product-order-form[_ngcontent-c2]{
height: auto;
}
should do the trick :)

Main container is not showing scrollbar

Hello All I hope you are doing Fine! So actually I'm working a chatroom and Im having problem displaying the messages. You see what is actually happening is that when i enter a message the message box goes down. Instead what I want is that I want the messages at the top go behind the navbar and I want the container which shows the message to show a scrollbar so the message send box will stay in place
my index.php
body {
overflow: none;
}
.container {
border: 2px solid #dedede;
background-color: #f1f1f1;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
overflow: auto;
}
.darker {
border-color: #ccc;
background-color: #ddd;
}
.container::after {
content: "";
clear: both;
display: table;
}
.container img {
float: left;
max-width: 60px;
width: 100%;
margin-right: 20px;
border-radius: 50%;
}
.container img.right {
float: right;
margin-left: 20px;
margin-right: 0;
}
.time-right {
float: right;
color: #aaa;
}
.time-left {
float: left;
color: #999;
}
<div class="container">
<p>
<div id="load_msg"></div>
</p>
<span class="time-right">11:00</span>
</div>
<div class="container darker">
<form method="POST" action="">
<input type="text" name="message" id="message_id" />
<button type="button" id="send_msg">Send</button>
</form>
</div>
You have two .container: One for the messages and another for the form. You need to separate the two, so give the container for the messages an id. TheN you set a height for the container with the id.
HTML
<div class="container" id="msg">...</div>
<div class="container">...</div>
CSS
#msg {
height: 100px;
}
Take a look at this link

Why is the height of my inline-block element smaller than the image inside of it?

.left-icons is inline-block and has a height of 21px:
Note that the height of the image inside of it is 38px:
CSS Tricks says:
If the height of the containing block is not specified explicitly, and
the element is not absolutely positioned, the value of its height
computes to auto (it will be as tall as the content inside it is, or
zero if there is no content).
The height of the containing block isn't being explicitly specified. So why is my outer element smaller than the image inside of it?
HTML
<div class='tango-directive-template'>
<div class='tango level-{{ level }}'>
<span class='left-icons'>
<img
ng-show='tango.children.length > 0'
src='/assets/images/show-arrow.png'>
<span class='author'>A</span>
</span>
<textarea
ng-focus='focus = true;'
ng-blur='focus = false;'
rows='1'>{{ tango.text }}</textarea>
<p class='menu' ng-show='focus'>
<span class='glyphicon glyphicon-indent-left'></span>
<span class='glyphicon glyphicon-indent-right'></span>
<span class='glyphicon glyphicon-arrow-down'></span>
<span class='glyphicon glyphicon-arrow-right'></span.
</p>
</div>
<tango
ng-repeat='subtango in tango.children'
tango='subtango'
level='{{ +level + 1 }}'>
</tango>
</div>
CSS
.tango-directive-template {
.tango {
margin-bottom: 20px;
.left-icons {
display: inline-block;
text-align: right;
width: 67px;
img, .author {
position: relative;
bottom: 15px;
margin-right: 5px;
height: 100%;
}
img {
height: 20px;
}
.author {
border: 1px solid gray;
border-radius: 25px;
padding: 10px;
}
}
textarea {
font-size: 18px;
width: 700px;
line-height: 135%;
padding: 8px 16px;
resize: none;
border: 1px solid white;
overflow: hidden;
}
textarea:focus {
outline: none;
border: 1px solid gray;
overflow: auto; // only have scroll bar when focused
}
.menu {
width: 750px;
span {
float: right;
margin-left: 15px;
cursor: pointer;
}
}
}
#for $i from 0 through 10 {
.level-#{$i} {
position: relative;
left: #{$i*65}px;
}
}
}
Use an inline block.
span.left-icons{
display: inline-block;
}
You probably should try a clearfix method.
Look here: What methods of ‘clearfix’ can I use?

Padding for placeholder without changing the size of input

I do adaptive search form. Search field should take 100% width of the parent div (the width of the parent div will change depending on the resolution of the device). The button "Search" should always be at the right of the field, do not shift down.
A working version.
But there's a problem: The text "Search now" (placeholder) too close to the edge of the field and I can't move it to the right. In other examples, it moves by the set value for the field padding. But if I change the padding — field itself is shifted to the left, but I only need to move the text!
#searchfield {
padding: 10px 0 13px 0; /* Try to change the left padding here! All field shifts to the left! But I need only shift the placeholder text to right! */
}
Try adding text-align:center for id searchfield or add box-sizing: border-box; declaration.
try with any one of below examples, it will move the placeholder to right as you expected, these will support Ie lower versions too.
Example1 (using box-sizing:border-box declaration)
#searchfield {
padding: 10px 0 13px 0px;
box-sizing: border-box;
}
Example2 (using text-align:center declaration)
#searchfield {
text-align:center;
}
You can still use padding to move the placeholder text, with the flavor of box-sizing: border-box; declaration.
box-sizing: border-box; make user-agents include padding/border to the width/height of the box.
#searchfield {
width: 100%;
border: 1px solid #ccc;
padding: 10px 0 13px 10px;
box-sizing: border-box;
/* other declarations... */
}
Vendor prefixes omitted due to brevity.
#sidebar {
width: 20%;
background: #ccc;
height: 300px;
padding: 20px;
}
#search {
width: 100%;
height: 50px;
position: relative;}
#searchfield {
width: 100%;
border: 1px solid #ccc;
margin: 0;
padding: 12px 0 13px 10px;
box-sizing: border-box;
position: absolute;
right: 0;
}
#searchsubmit {
width: 60px;
height: 41px;
background: red 0 0;
border: 0;
overflow: hidden;
cursor: pointer;
right: 0;
position: absolute;
}
<html>
<body>
<div id="sidebar">
<div id="search">
<form id="searchform" method="get" action="/index.php" _lpchecked="1">
<input type="text" name="s" id="searchfield" placeholder="Search now">
<input type="submit" id="searchsubmit" value="Search">
</form>
</div>
</div>
</body>
</html>
It's worth mentioning that border-box is supported in IE8+ as well as modern web browsers.
This could do the trick for you. It solved the issue I was having.
Tried on firefox and chrome
.random-class-name{
text-indent: 10px;
}
Text written inside the input is indented as well.
No need to use position absolute. try this code:
<html>
<body>
<div id="sidebar">
<div id="search">
<form id="searchform" method="get" action="/index.php" _lpchecked="1">
<input type="text" name="s" id="searchfield" placeholder="Search now">
<input type="submit" id="searchsubmit" value="Search">
</form>
</div>
</div>
</body>
</html>
#sidebar {
width: 20%;
background: #ccc;
height: 300px;
padding: 20px;
}
#search {
width: 100%;
height: 50px;
position: relative;}
#searchfield {
width: calc(100% - 60px);
border: 1px solid #ccc;
margin: 0;
padding: 10px 0 13px 20px; /* Try to change the left padding here! All field shifts to the left! But I need only shift the placeholder text to right!
position: absolute;*/
right: 0;
float:left;
box-sizing:border-box;
}
#searchsubmit {
width: 60px;
height: 41px;
background: red 0 0;
border: 0;
overflow: hidden;
cursor: pointer;
right: 0;
float:left;
box-sizing:border-box;
}
live demo on code pen

Resources