How to repeat character in HTML with responsive resizing? - javascript

I am trying to create rows in a DIV where there are three pieces of information to display. A left align text, a right align text, and repeat character "." between the two
I tried this using the HTML below. But it is not working with a div for each piece.
<div style="margin-bottom:5px"><!-- row 1 -->
<div style="float:left;">Left</div> <!-- left column -->
<div style="display: inline-block;">...</div> <!-- center column -->
<div style="float:right;">Right</div> <!-- center column -->
</div><!-- row 1 -->
I believe it most likely has to be done using just one div displaying one piece of text/string where the "." character gets repeated between the other two pieces of text. I cant figure it out so that the string changes with the DIV size - in order to keep it responsive.

You could achieve that rather simply with flexbox and a dotted border.
.row { display: flex; }
.center {
flex-grow: 1;
border-bottom: 2px dotted black;
margin: 0 4px 4px;
}
<div class="row">
<div class="left">Left</div>
<div class="center"></div>
<div class="right">Right</div>
</div>
<div class="row">
<div class="left">This is some longer left text</div>
<div class="center"></div>
<div class="right">Right</div>
</div>
<div class="row">
<div class="left">Left</div>
<div class="center"></div>
<div class="right">This is some longer right text</div>
</div>
Make parent display: flex so that children align side-by-side.
Add flex-grow: 1 to the center so that it fills empty space
Add border-bottom: 2px dotted black to achieve your dotted line
Add some margins to position and pad the dotted line properly

You could do something like this :
<div class="row>
<div class="left"> Left </div>
<div class="middle"></div>
<div class="right"> Right </div>
</div>
And use flexbox to set the sizes:
.row { display: flex; }
.left , .right { flex: 0 0 auto; } /* will not shrink or grow, with their default width set to auto */
.middle { flex: 1 1 0; } /* will shrink/grow to fill all available space, with a default width of 0 */
Now, you could apply something like:
.middle {
position: relative;
border-bottom: 1px dotted currentColor;
transform: translateY(-.4em); /* change to reposition vertically */
}
You can also add spacing by :
.left { padding-right: 1em; }
.right { padding-left: 1em; }

Related

CSS Grid two rows nested in a single column

I am looking for a way to allow two rows within a single column while the other two columns to the right of it are equal/flexible to the height of those two rows. The width should be 100% when looking at all three columns (so around 33% each column). Here is an example of how I want it to look:
https://i.imgur.com/lLPzXhS.png
I will be filling those boxes with clickable boxes like shown below:
https://i.imgur.com/uyyDbL7.png
I have tried using display: row, display: cell, but I am not able to add any margins to it so this is the product I get:
https://i.imgur.com/Ok6EgT0.png
You can see that I have somewhat of the grid system set up, but not as ideally as I want it. There are no margins that can be set between the red and orange box, even though I am able to add margins to the turqoise and blue box.
Here is the code I have:
HTML:
<div class='d-table'>
<div class='t-row'>
<div class='t-cell one-third'>
<div class='turqoisebox'>
Turqoise box here
</div>
<div class='bluebox'>
Blue box here
</div>
</div>
<div class='t-cell one-third redbox'>
Red box here
</div>
<div class='t-cell one-third orangebox'>
Orange box here
</div>
</div>
</div>
CSS:
.d-table {
display: table;
}
.t-row {
display: table-row;
}
.t-cell {
display: table-cell;
margin-left: unset;
margin-right: unset;
/*border: 1px solid tomato;*/
}
.one-third {
width: 30%;
}
.two-thirds {
width: 200px;
}
.bluebox {
background-color: #9dd8dd;
margin: 25px;
border-radius: 25px;
border: solid #7dacb0;
border-width: 3px;
box-shadow: 2px 4px 8px 2px rgba(0,0,0,0.4);
transition: 0.3s;
text-align: center;
}
.bluebox:hover {
box-shadow: 2px 8px 16px 2px rgba(0,0,0,0.8);
}
Any thoughts on how to replicate the second image results neatly?
You could use flexbox. Take a look at this simplified example:
.content {
background: orange;
margin: 1rem;
padding: 1rem;
flex: 1;
color: white;
display: flex;
}
.content > span {
margin: auto;
}
.row {
display: flex;
flex-direction: row;
background-color: blue;
flex: 1
}
.col {
display: flex;
flex-direction: column;
flex: 1;
background-color: red;
}
<div class="row">
<div class="col">
<div class="row">
<div class="content">
<span>This is centered</span>
</div>
</div>
<div class="row">
<div class="content">
<span>This is centered</span>
</div>
</div>
</div>
<div class="col">
<div class="content">
<span>This is centered</span>
</div>
<div class="content">
This is not
</div>
<div class="content">
This is not
</div>
</div>
<div class="col">
<div class="content">
This is not
</div>
<div class="content">
This is not
</div>
<div class="content">
This is not
</div>
<div class="content">
<span>This is centered</span>
</div>
</div>
</div>
You could also use a minimal flexbox-based grid library like Flexbox Grid.
Margin is used for setting where elements should start so instead use padding between those 2 elements to get the space you want.

Div expand to size of certain content

I have a bunch of divs that have a content div inside of them. In the content div are 3 elements, an h1, a p and a span, all left-aligned. What I want to happen is the following:
The content div should be vertically and horizontally centered
The content div should be exactly as wide as the text in the h1 or the text in the span (whichever is longer), if above the max-width these should wrap
The p should be 75% as wide as the content div but not have an impact on the content div's size (effectively being 75% as wide as the h1 or span, whichever is longer)
However I'm running into the following problems:
Problem 1: Having a long p element causes the content div to expand to its max-width no matter the size of the h1 or span. I've tried using absolute positioning to fix this but it disrupts the vertical centering of the div
Problem 2: Having a long h1 element leaves a gap where the word breaks over 2 lines making the content div not appear centered
See the code snippet below to clarify what I'm after and what's going wrong, the borders are just to help visualise what's happening.
Has anyone got an idea of how this is possible? I would like to stick to CSS as these need to be responsive, although if there is a simple JS/jQuery solution it would be considered.
EDIT: To clarify the visual effect I am after here's a run-down of why the examples are good or bad. I've also added the ability to remove borders to demonstrate what I mean by something being visually centred:
1) Good: Content div fits to width of h1, looks centered without the borders as equal space to left and right of h1
2) Good: Content div fits to width of span as it's longer than the h1, looks centered without the borders as equal space to left and right of span
Problem 1:
3) Bad: p is expanding the width of the content div, looks shifted to the left without borders as more space on right than left. If the p did not expand the div and stayed at 75% of the width this would not happen
4) Improvement on 3 but still bad: Potential fix found in various SO questions showing absolute positioning stops the p expanding the content div, but now that it is not part of the flow it messes up the vertical centering
Problem 2:
5) Bad: The problem here is the h1 element, because it is now longer than the max-width it splits into 2 lines. But the extra space between the end of the first line and the max-width of the div is kept so when removing borders it doesn't look centered because there is more space to the right than the left of the h1
6) Fixes 5 but not a solution: Manually breaking the line (using a <br>) achieves the look I need, because the h1 isn't expanded to the max-width so looks centered without the borders. This isn't feasible in the real application though because the divs can vary in width
Alternative JSFiddle Link
function toggleBorders() {
$('h1, p, span').toggleClass('bordered');
$('.content').toggleClass('content-bordered');
}
.box-holder {
display: flex;
flex-flow: row wrap;
}
.box {
flex: 0 0 380px;
display: flex;
align-items: center;
justify-content: center;
height: 350px;
border: 1px solid blue;
}
.content {
max-width: 80%;
position: relative;
}
.content-bordered {
border: 1px solid red;
}
.bordered {
border: 1px solid green;
}
p {
width: 75%;
}
.abs {
position: absolute;
}
button {
position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="toggleBorders()">Toggle Borders</button>
<div class="box-holder">
<div class="box">
<div class="content">
<h1>1. Example Title</h1>
<p>Good Example</p>
<span>Example link to the article</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>2. Title</h1>
<p>Min Width Good Example</p>
<span>Example link to the article</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>3. Example Title</h1>
<p>But when the description gets too long then it expands the content div</p>
<span>Example link to the article</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>4. Example Title</h1>
<p class="abs">Setting absolute position avoids expansion but messes up the vertical layout</p>
<span class="abs">Example link to the article</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>5. Also Long Titles Leave White Space</h1>
<p>This doesn't look centered, see 6</p>
<span>Example link to the article</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>6. Also Long Titles<br>Leave White Space</h1>
<p>Manually breaking lines fixes this</p>
<span>Example link to the article</span>
</div>
</div>
</div>
So the answer to both of these questions, it seems, is that you cannot do this without javascript. The reason being that the CSS box model just does not work in this way.
In order to solve just the first problem you need to use absolute positioning like I tried but then use javascript to create a space for the element using a margin on the h1, something like this:
$(document).ready(function() {
function alignDescriptions() {
var pmargin = 10 * 2;
$('.abs').each(function() {
var pheight = $(this).height();
$(this).css('bottom', pmargin);
$(this).siblings('h1').css('margin-bottom', pheight + pmargin);
});
}
});
That solves the vertical centering issue when using absolute so problem 1 is fixed.
To solve the second problem, the following answer provides one solution: https://stackoverflow.com/a/33246364/7542390
I believe simply using this but also using the width of the span as a minimum would probably solve both problems as I would be literally forcing the width to the correct size so having a 75% width p element wouldn't be a problem.
It's a shame that this kind of functionality isn't in the CSS spec.
EDIT: As suspected, an adaption of the second option actually removes the need for absolute positioning of the p element. Here's the jQuery code that worked for my actual case:
$('h1').each(function() {
// references to elements
var hElem = $(this);
var pElem = hElem.siblings('p');
var sElem = hElem.siblings('span');
// store starting values
var sWidth = sElem.width();
var hHeight = hElem.height();
var hWidth = hElem.width();
// reduce width until less than span width
// or until height of h1 changes
for (var testWidth = hWidth - 1; testWidth > 0; testWidth--) {
if (testWidth <= sWidth) {
testWidth = sWidth - 1;
break;
}
hElem.width(testWidth);
if (hElem.height() !== hHeight) break;
}
// set h1 width
hElem.width(++testWidth);
// if h1 still overflows (long word) use that instead
if (hElem[0].scrollWidth > hElem.width()) {
testWidth = hElem[0].scrollWidth;
hElem.width(testWidth);
}
// set p element to 75% width
pElem.width(testWidth * 0.75);
});
Your question is very interesting.I have solved your div expansion of the description by setting the max-width as the same as your min-width. Then it cannot expand.
I can't figure out the problem with the white space and title. It looks centred to me.
Here is what I got:
.box-holder {
display: flex;
flex-flow: row wrap;
}
.box {
flex: 1 0 350px;
display: flex;
align-items: center;
justify-content: center;
height: 350px;
border: 1px solid blue;
}
.content {
min-width: 50%;
max-width: 50%;
border: 1px solid red;
}
h1,
p,
span {
border: 1px solid green;
}
p {
width: 75%;
}
.abs {
position: absolute;
}
<div class="box-holder">
<div class="box">
<div class="content">
<h1>1. Example Title</h1>
<p>Good Example</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>2. Title</h1>
<p>Min Width Good Example</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>3. Example Title</h1>
<p>When the description gets too long then it DOESN'T expand the content div</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>4. Example Title Size</h1>
<p class="abs">Setting absolute position avoids expansion but messes up the vertical layout</p>
<span class="abs">Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>5. Also Long Titles Leave White Space</h1>
<p>This does look centered</p>
<span>Link</span>
</div>
</div>
</div>
I hope it helps and this is what you're looking for.
EDIT
Solving 5 with text-align: justify;
.box-holder {
display: flex;
flex-flow: row wrap;
}
.box {
flex: 1 0 350px;
display: flex;
align-items: center;
justify-content: center;
height: 350px;
border: 1px solid blue;
}
.content {
min-width: 50%;
max-width: 50%;
border: 1px solid red;
}
h1,
p,
span {
border: 1px solid green;
}
p {
width: 75%;
}
.abs {
position: absolute;
}
/*NEW CSS:*/
h1 {
text-align: justify;
}
<div class="box-holder">
<div class="box">
<div class="content">
<h1>1. Example Title</h1>
<p>Good Example</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>2. Title</h1>
<p>Min Width Good Example</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>3. Example Title</h1>
<p>When the description gets too long then it DOESN'T expand the content div</p>
<span>Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>4. Example Title Size</h1>
<p class="abs">Setting absolute position avoids expansion but messes up the vertical layout</p>
<span class="abs">Link</span>
</div>
</div>
<div class="box">
<div class="content">
<h1>5. Also Long Don't Titles Leave White Space</h1>
<p>This does look centered</p>
<span>Link</span>
</div>
</div>
</div>

How to left-align centered text only if hits a line break?

How can I condition my text to become left-aligned if hits the end of its contained space and has to switch to the next line? Is there something inherent within CSS that can detect it, or does it have to be a JavaScript solution?
Here's the fiddle so you can see how it should behave: https://jsfiddle.net/fj4ddmey/2/
.text.container {
margin: 0 auto;
text-align: center;
width: 350px;
border: 1px solid black;
}
.text.container.two {
text-align: left;
}
<div class="text container">
<p>This is how short sentences should look</p>
</div>
<div class="text container">
<p>This text should be left aligned because it hits a line break</p>
</div>
<div class="text container two">
<p>This is how it should look, but it needs to be a fluid solution</p>
</div>
Use flexbox like that
.container {
display: flex;
justify-content: center;
}
<div class="container">
<p>This is how it should look, but it needs to be a fluid solution</p>
</div>
Here is JSFiddle demo
You can set the <p> as inline block, so that text-align:center on the container will center the <p> tag first, rather than the text. And inline-block has the shrink-to-fit feature, means the width is determined by the content, and never goes beyond the container, with text-align:left, text inside will be left aligned when it wraps.
.container {
width: 350px;
margin: 0 auto;
text-align: center;
outline: 1px solid black;
}
.container p {
display: inline-block;
text-align: left;
outline: 1px dotted red;
}
<div class="container">
<p>This is how short sentences should look</p>
</div>
<div class="container">
<p>This text should be left aligned because it hits a line break</p>
</div>
You can use jQuery to determine the element height, and if its greater than one line, add a class to justify the text appropriately.
Something like this should work:
function countLines(e) {
var elementHeight = e.innerHeight();
var lineHeight = parseInt(e.css('line-height'));
var lines = elementHeight / lineHeight;
return(lines > 1);
}
$('p').each(function() {
if(countLines($(this))) {
$(this).addClass('two'); //class to left justify
}
})
You can see it working here: https://jsfiddle.net/igor_9000/fj4ddmey/1/

Nested flexboxes and items alignment

I'm trying to create my own small grid system based on CSS3 flex display. I basically have the following classes:
a grid class, which is a flex container with flex-direction set to column.
a row class, which is a flex container with flex-direction set to row.
set of column classes of different flex-basis sizes.
What I want is to be able to align each row to the left/center/right by setting the self-align property of the row element. However, whenever I try to do it, things seem to go bad.
Here is a plunker that demonstrate it:
http://plnkr.co/edit/mHOs7U28GCBJuPvi7ikJ?p=preview
HTML
<!-- first row -->
<div class="row align-end"> <!-- try to remove 'align-end' here -->
<div class="column-1">
<div class="item">1</div>
</div>
<div class="column-1">
<div class="item">2</div>
</div>
</div>
<!-- second row -->
<div class="row">
<div class="column-1">
<div class="item">3</div>
</div>
<div class="column-2">
<div class="item">4</div>
</div>
</div>
</div>
CSS
* {
box-sizing: border-box;
}
.grid {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
}
.column-1 {
flex-basis: 33.33%;
padding: 10px;
}
.column-2 {
flex-basis: 66.67%;
padding: 10px;
}
.column-3 {
flex-basis: 100%;
padding: 10px;
}
.align-start {
align-self: flex-start;
}
.align-center {
align-self: center;
}
.align-end {
align-self: flex-end;
}
.item {
background-color: lightblue;
font-family: "Arial";
text-align: center;
padding: 4px;
}
As you can see, In this plunker I set up a grid with two rows, with two columns in each row. The two columns in the first row have a width of 33.33% (flex-basis). In the second row, the first column's width is 66.67% and the second column is 33.33%. Now, since the first row has some unused space, I want to try to align it to the right (for whatever reason). Therefore, I add to the div that represents the first row the class align-end, which basically just adds the property align-self: flex-end; to the element.
As you can see, by doing so the first row looks bad, both columns are aligned to the right, but their width is totally corrupted (you can try and remove the class 'align-end' from the first row, and things will get back to normal).
What am I missing? Why the row doesn't align correctly to the right?
Thanks,
Roy.
The property that controls how the children are aligned along the main axis is justify-content
.align-end {
justify-content: flex-end;
}
plunker
is this whats you're going for?
http://plnkr.co/edit/bFWMSQ7qj4Cuomzm0Ptv?p=preview
Looks like you had 2 column-1 class in the first row
<!-- first row -->
<div class="row align-end"> <!-- try to remove 'align-end' here -->
<div class="column-1">
<div class="item">1</div>
</div>
<div class="column-1">
<div class="item">2</div>
</div>
</div>
********edit*********
after some digging i think i know what you mean.
you are trying to left align the first box and right align the second box leaving a blank in the middle.
if you add margin-left: auto; it takes care of the rest of the space left in the row.
http://plnkr.co/edit/1Eoeh4uOik3BIZHsL9bH?p=preview
i added it to the align-end class so whenever you use align-end, it will add the margin-left:auto; to that box.

Position stack of div in column

I have three div contained in one, making a box. I have five boxes.
I would find a solution in CSS or in jQuery to display them In 3 columns instead of only one.This without picking out any line of code from the current structure (however I can add some).
Here is the JSFiddle :
<div class = "box">
<div class = "boxTitle"> My title</div>
<div class = "boxContent"> My content</div>
<div class= "botBottom"> </div>
</div>
<div class = "box">
<div class = "boxTitle"> My second title</div>
<div class = "boxContent"> My second content</div>
<div class= "botBottom"> </div>
</div>
http://jsfiddle.net/Fayastone/C8XGU/3/
Does anyone have an idea ?
Thank you very much for reading me,
Hugo.
The responsive solution..
You can make a responsive layout using column-count, wrap your boxes with <div class='columns'> then use the below CSS, try resizing the window to see how the layout is dynamically updated:
Demo Fiddle
.box {
border : 2px inset grey;
border-radius : 6px;
break-inside: avoid-column;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
margin-bottom:30px;
}
.boxTitle {
color : #FF6600;
border : 2px inset grey;
}
.columns {
-webkit-column-width: 20em;
-webkit-column-gap: 2em;
-webkit-column-rule: 1px solid #eee;
-webkit-column-count: 3;
-moz-column-width: 20em;
-moz-column-gap: 2em;
-moz-column-rule: 1px solid #eee;
-moz-column-count: 3;
-ms-column-width: 20em;
-ms-column-gap: 3em;
-ms-column-rule: 1px solid #eee;
-ms-column-count: 3;
column-width: 20em;
column-gap: 2em;
column-rule: 1px solid #eee;
column-count: 3;
}
There are three conventional ways to do this.
1 - Floats
Floats work in all major browsers. If you're new to CSS, they can be a bit tricky to get used to (read up clearing floats and check out SO for info too!).
.box{
border : 2px inset grey;
border-radius : 6px;
/* new stuff */
float : left;
width : 30%;
margin : 0 1.5%;
box-sizing : border-box; /* for box layout */
}
Check out the updated fiddle using floated boxes!
2 - Using display:inline-block
Another (arguably better) approach is to change the divs' display properties. inline-block is a good value because it doesn't force the box to stretch full width, but it still allows very flexible use of CSS on the div's box.
Problem is that display: inline-block is not properly supported in Internet Explorer 7 or below.
.box{
border : 2px inset grey;
border-radius : 6px;
/* new stuff */
display : inline-block;
width : 30%; /* for three columns */
margin : 0 1.5%; /* for box layout */
box-sizing : border-box; /* for box layout */
}
Check out my fiddle using display: inline-block!
3 - Imitating a <table>
This one is more complicated, but it allows you to easily ensure that each column is the same height.
You need to wrap your columns in another element to serve as the column container, and then you just make a few CSS changes. You are forcing your divs to behave like a <table> using CSS:
HTML
<div class="wrapper"><!-- new table wrapper -->
<div class = "box">
<div class = "boxTitle"> My title</div>
<div class = "boxContent"> My content</div>
<div class= "botBottom"> </div>
</div>
<div class = "box">
<div class = "boxTitle"> My second title</div>
<div class = "boxContent"> My second content</div>
<div class= "botBottom"> </div>
</div>
<div class = "box">
<div class = "boxTitle"> My second title</div>
<div class = "boxContent"> My second content</div>
<div class= "botBottom"> </div>
</div>
</div>
CSS
.wrapper {
display : table;
width : 100%; /* ensure table takes full width */
}
.box{
border : 2px inset grey;
border-radius : 6px;
width : 33.3%; /* even out the width */
display : table-cell; /* This allows them to be side by side */
}
Check out the display: table-cell layout on jsFiddle!
Here is an update to your fiddle:
http://jsfiddle.net/C8XGU/12/
.box{
border : 2px inset grey;
border-radius : 6px;
width:33%;
display:inline-block;
margin:-2px;
}
The css of the box class has been updated.
You want the boxes to be in separate columns? Like this?
.box{
border : 2px inset grey;
border-radius : 6px;
width:33%;
float:left;
}
JSFiddle
Like this? display:inline-block
http://jsfiddle.net/C8XGU/10/

Categories