Middleman: dynamic background image? - css

Some background info:
I just started learning middleman to build my portfolio.. I don't have a programming background, so bear with me :-).
I have an index page where I list all my projects like cards, created / populated by data from a json file. This is the loop I use to create the cards for each project on the index page:
<div class="row">
<% data.projects.projects.each do |project| %>
<div class="col-md-12">
<h2>
<%= project.title %>
</h2>
<div>
<%= link_to 'View project', project.path, relative: true %>
</div>
</div>
<% end %>
</div>
This is the json file from which I set the project title and url:
{
"projects": [
{"title": "One",
"path": "/one.html"
},
{"title":"Two",
"path": "/two.html"
},
{"title":"Three",
"path": "/three.html"
}
]
}
So far, so good.
Now what I want to do is to set a (unique) background image for each card, and I'm not quite sure how to do it. As I see it, there are two approaches I could take:
1. Create the CSS rules for each card and set the class in the loop from json:
bg-img-1 { background-image: url("img1.jpg"); }
bg-img-2 { background-image: url("img2.jpg"); }
bg-img-3 { background-image: url("img3.jpg"); }
and add { "bg-img": "bg-img-x" } in each project in the json file.
and then in my card creating loop add the 'bg-img' to the class of each card.
2. Set an inline style on the div, and inject the img path from the json file:
<div class="card" style="background: url(<%= data.project.img %>)"> </div>
However, neither of these solutions seem elegant / optimal?
With solution #1 making a change becomes tedious as I would have to make changes in several places, the CSS & json file.
Solution #2 doesn't have that issue, but I'm not a fan of inline styling / having styling saved in separate places.
So is there another way of doing this? Or do I have to pick one of these and deal with the pro's & cons of each?
Thanks!

Solution #2 is completely fine and often used. inlining style for the background is a standard practice

Related

How to change a link_to hover image in Rails 4 with an asset pipeline

Note: This explanation is targeted for beginners.
I was facing the problem of not being able to change the image in a link_to when I hovered over the image. Nothing I did in CSS seemed to solve the problem. I present my solution to this problem below.
This is my link_to:
<%= link_to image_tag('1487789814_back.png'),
{controller: #controller_action_hash_from_params[:controller],
action: #controller_action_hash_from_params[:action]},
sql_text: #sql_text,
:id => "ralph-back-button-black-img", :class => "ralph-fieldset-back-button" %>
1487789814_back.png is an ordinary png in app/assets/images. It happens to be a black arrow pointing left. Similarly, app/assets/images/1487789814_back_red.png (used below) is a red arrow pointing left. I wanted the red arrow to appear when I hovered over a fieldset containing the black arrow.
The source of the problem:
The link_to above generates/generated the following HTML:
<img src="https://localhost:3000/assets/1487789814_back-731afaae70e04062b25988079e4ef8ab4e6b523f4ac11ff7d142a9ff01e63455.png" alt="1487789814 back">
Note:
The file https://localhost:3000/assets/1487789814_back-731afa...3455.png" will not exist for you. It's a filename automatically generated by Rails
Analysis:
The problem comes, in part, because (I believe) css cannot override HTML. That is, if you specify an attribute (e.g. width) in your HTML, you cannot override that in css. Similarly, (I believe) you cannot override the src="https: ..." in css. Any attempt (I believe) to use :hover will fail. To make this work, you'll need a bigger hammer: javascript or jquery.
My solution:
Please note: I am not claiming this solution is the best solution or even a good solution. I am claiming it works in my Rails 4 environment.
If you are using the asset pipeline in Rails 4 (Rails 3? Rails 5?), your "friendly" image names (in my case 1487789814_back.png and 1487789814_back_red.png) will be converted by the asset pipeline system into names with a cryptographic hash appended. In other words, to get access to the red arrow image you need to know what name Rails assigned to your image. It is beyond the cope of this little article to explain why Rails renames your image file; just know that it does. (Of course, your original file will still be there with its original name.)
So somehow we must "map" the friendly name (e.g. "1487789814_back.png") to the name in the asset pipeline.
I accomplished this by creating a div with "display:none" css.
erb:
<%# This div has display:none.
We do this in order to preload the images_path as well as create a "map"
between the friendly name and the asset pipeline name
%>
<div class='ralph_preload'>
<%= image_tag('1487789814_back.png', options={class:'ralph_preload_class', id:'1487789814_back'}) %>
<%= image_tag('1487789814_back_red.png', options={class:'ralph_preload_class', id:'1487789814_back_red'}) %>
</div>
The erb above generated the following HTML:
<div class="ralph_preload">
<img class="ralph_preload_class" id="1487789814_back" src="/assets/1487789814_back-731afaae70e04062b25988079e4ef8ab4e6b523f4ac11ff7d142a9ff01e63455.png" alt="1487789814 back">
<img class="ralph_preload_class" id="1487789814_back_red" src="/assets/1487789814_back_red-bbd0f2e34f3401cc46d2e4e1e853d472d8c01c9a75f96d78032738bd01b2133b.png" alt="1487789814 back red">
</div>
The associated css is:
.ralph_preload {
display: none;
}
I created some jQuery to change the black arrow to red when the user hovers:
<script type="text/javascript">
function get_precache_myStruct_array(outer_div_class){
var myStruct_array = [];
$('.'+outer_div_class).find(".ralph_preload_class").each(function(){
var myStruct = {
id: this.id,
src: this.src
};
// myStruct_array.push(myStruct);
myStruct_array[this.id] = myStruct;
});
return myStruct_array;
}
// See http://stackoverflow.com/questions/15352803/how-to-check-if-an-image-was-cached-in-js
function is_cached(img_url){
var imgEle = document.createElement("img");
imgEle.src = img_url;
return imgEle.complete || (imgEle.width+imgEle.height) > 0;
}
$(document).ready(function(){
var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
$.each(precache_myStruct_array,
function (index, value) {
if (!is_cached(value.src)) {
alert("Not cached!: " + value.src);
};
});
<% if true %>
$('#ralph-back-button-filedset').hover(function(){
var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
var imageID = '1487789814_back_red';
$('#ralph-back-button-black-img > img:nth-child(1)').attr("src", precache_myStruct_array[imageID].src);
}, function(){
var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
var imageID = '1487789814_back';
$('#ralph-back-button-black-img > img:nth-child(1)').attr("src", precache_myStruct_array[imageID].src);
});
<% end %>
});
</script>
You might notice a "<% if true %>" / <% end %> block in the jQuery. Since the jQuery is "inlined" into the .erb file, the jQuery goes through erb processing. By changing the true to false, it can make using browser debuggers easier to use.
Conclusion:
I did a search on the web to find the answer to my problem. I found none that is, as the lawyers say, on point.
I am, of course, enthusiastically open to corrections and comments.
If you put those images in your public folder, they will not get the extra hash added to the image name.
With that said, I ran a loop in my controller that got me all the "Rails" file names for my images and stored them somewhere I could access them easily.

How to make my background image appear only on one page in rails 4?

I have a background image that I can not get to stay just on one page. I have made a welcome controller with one home view to display it. I am precompiling my assets as well. The background shows up just fine, but my goal is to just show the background image on my home.html.erb view.
welcome/home.html.erb:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= I18n.locale || 'en' %>"
lang="<%= I18n.locale || 'en'%>">
<body class="container">
<h1>title</h1>
</body>
</html>
welcome controller:
class WelcomeController < ApplicationController
def home
end
end
stylesheets/welcome.css.scss:
body
{
background: {
image: asset-url("image.jpg");
}
}
and I have the following in my application layout:
<head>
<%= stylesheet_link_tag "welcome" if controller_name == "welcome" %>
</head>
and in config/initializers/assets.rb :
Rails.application.config.assets.version = '1.0'
Rails.application.config.assets.precompile += %w( welcome.css )
Add specific css,
body.welcome
{
background: {
image: asset-url("image.jpg");
}
}
and in html,
<body class="container welcome">
You must be wondering even though you have not included specific file then why it is applying all over. This is because you must have specified require_tree . in application.css
In Rails:
Try creating a css class for the background image
.splash {
background-image: image-url("image.jpeg");
background-size: cover;
background-position: center;
background-attachment: fixed;
}
If you want all pages to display the image
<html class="splash"> ... </html>
But on one page only, on that view page, wrap everything in
<body class="splash"> ... </body>
You are overriding body for the entire application. Make a class instead and call it using div on the page you want to display the background image.
Also, you are calling the use of the stylesheet from the application layout rather than the page itself.
Stylesheet
#app/views/layouts/application.html.erb
<head>
<%= stylesheet_link_tag controller_name if controller_name == "welcome" && action_name == "home" %>
</head>
#app/assets/stylesheets/welcome.css.scss
body {
background: {
image: asset_url("image.png");
}
}
#config/application.rb
config.assets.precompile += %w(welcome.css)
This should load the welcome stylesheet if you're visiting the welcome#home view. I would strongly recommend against using classes to determine this page - it's far cleaner to include a stylesheet, as this will give you scope to extend the functionality as you wish
--
Test
To test this, you should first look at whether your welcome.css is being loaded when you hit the welcome#home view. To do this, you just need to right-click > view-source.
If the stylesheet is present, you'll want to ensure your styling is performing correctly. This will be trickier to debug, but will just entail you looking at the loaded CSS file & seeing what it's doing with the elements on your page.
If you do the above, comment as to whether you're seeing the welcome.css in your source. If you are, it's a good sign, and we'll be able to look at the CSS after that
Your welcome.css file is being included by the asset pipeline so will apply the background on every page. In order to apply the background image to the body only on the home page, you need to apply a class to the body when the home page displays.
However, if you are correctly using layouts, the opening <body> tag will be in your application.html.erb or in a partial so not available in your home.html.erb. You will need it to add it dynamically so I suggest you use a small jQuery script at the end of your home template.
<script>$('body').addClass('home-page');</script>
Then you can amend your CSS to
body.home-page {
background: {
image: asset-url("image.jpg");
}
}
That should give you the results you require.

How can I get Sitecore Field Renderer to use a css class for an image

Using Sitecore (7) & MVC, I'd like to know how to add a css class attribute for an image to the field renderer in sitecore.
Without Sitecore it looks like this:
<div class="background-container">
<img src="/images/background-1.jpg" class="background">
</div>
With Sitecore:
<div class="background-container">
#Html.Sitecore().Field(Constants.Fields.HomeBackgroundImage)
</div>
There doesn't seem to be a way to add the class background to the image itself in Sitecore. Is there another way to do this?
Thanks.
This was what I was looking for:
#Html.Sitecore().Field("MyFieldName", myItem, new { Parameters = new SafeDictionary<string> { { "enclosing-tag", "h2" } } })
See Extending the Sitecore RenderField pipeline.

ruby on rails css

I'm trying to color my view using css. The controller is workflows_controller. Hence i added the following code to the workflows.css.scss:
.folder_section {
text-align:center;
color: #244;
}
My view is
<div class="folder_section" id="folder_section">
<%= form_for :folder_name, :remote => true, :method => "get", :url => {:action => "show"} do |f| %>
<%= f.select :foldernames, options_for_select(#folders, #folders.first)%>
<%= f.submit "Submit folder"%>
<% end%>
</div>
The select box is aligned to the center but i could not see any color. I copy pasted the same code in the view itself. But still i could not see any color. Please let me know why the select box is aligned to the center but not colored. I looked into the web and some pdf documents. Everyone says that the controller.css.scss will take care of styling when you add the css code to it.
Thanks
The css color attribute is for setting the font color and the color you chose is quite close to black so you may not see a change.
Have you tried to set the background-color attribute to #244?
Or try to change the select field color attribute by defining it in the code
.folder_section {
select {
color: #244;
}
}

How do I use CSS with simple form?

I have a text_area that is showing up with a height that is too large.
I am using simple form and I have read their documentation, but am still unclear on how to apply a css class to a text_area.
My form:
<div class="field">
<p>What's on your mind?</p>
<%= f.text_area :content, :wrapper_html => { :class => 'height-100px' }, placeholder: "Thought leads to action..." %>
</div>
My css:
.height-100px {
height:100px;
}
When I apply CSS to a div surrounding the input field it truncates the height, but inserts a scrollbar. Clearly, I am not applying the right css in that case.
I think this is an easy question to answer, but let me know. Thanks!
I ended up applying the class name "mf" to the section and using the generic "textarea" element to style all textareas on the site using this:
.mf {
textarea {
height:50px;
}
}
Would have been nice to apply the class name directly on the simpleform element, but it would not work for me...

Resources